* Updated to jitcache-arm-x86 branch d4f6023b26c5+d1b5b1c106ac
authorRobert Schuster <robertschuster@fsfe.org>
Fri, 10 Oct 2008 14:17:15 +0000 (16:17 +0200)
committerRobert Schuster <robertschuster@fsfe.org>
Fri, 10 Oct 2008 14:17:15 +0000 (16:17 +0200)
--HG--
branch : jitcache-arm-x86
rename : src/vm/builtin.c => src/vm/jit/builtin.cpp
rename : src/vm/builtin.h => src/vm/jit/builtin.hpp
rename : src/vm/jit/code.c => src/vm/jit/code.cpp
rename : src/vm/jit/code.h => src/vm/jit/code.hpp
rename : src/vm/jit/codegen-common.c => src/vm/jit/codegen-common.cpp
rename : src/vm/jit/jit.c => src/vm/jit/jit.cpp
rename : src/vm/jit/patcher-common.c => src/vm/jit/patcher-common.cpp
rename : src/vm/jit/patcher-common.h => src/vm/jit/patcher-common.hpp

458 files changed:
THIRDPARTY
configure.ac
m4/ax_compiler_vendor.m4 [new file with mode: 0644]
m4/dl.m4
m4/jmm.m4 [new file with mode: 0644]
m4/jvm.m4 [new file with mode: 0644]
m4/vm-zip.m4 [new file with mode: 0644]
src/cacao/cacao.cpp
src/classes/Makefile.am
src/mm/Makefile.am
src/mm/cacao-gc/final.h
src/mm/cacao-gc/gc.c
src/mm/cacao-gc/gc.h
src/mm/cacao-gc/heap.c
src/mm/cacao-gc/heap.h
src/mm/cacao-gc/rootset.c
src/mm/cacao-gc/rootset.h
src/mm/codememory.c
src/mm/dumpmemory.c [deleted file]
src/mm/dumpmemory.cpp [new file with mode: 0644]
src/mm/dumpmemory.h [deleted file]
src/mm/dumpmemory.hpp [new file with mode: 0644]
src/mm/gc-boehm.cpp
src/mm/gc-none.cpp
src/mm/gc.hpp
src/mm/memory.c
src/mm/memory.h
src/mm/tlh.h
src/native/Makefile.am
src/native/jni.cpp
src/native/jni.h [deleted file]
src/native/jni.hpp [new file with mode: 0644]
src/native/jvmti/cacaodbg.c
src/native/jvmti/jvmti.c
src/native/jvmti/jvmti.h
src/native/llni.h
src/native/localref.c [deleted file]
src/native/localref.cpp [new file with mode: 0644]
src/native/localref.h [deleted file]
src/native/localref.hpp [new file with mode: 0644]
src/native/native.c [deleted file]
src/native/native.cpp [new file with mode: 0644]
src/native/native.h [deleted file]
src/native/native.hpp [new file with mode: 0644]
src/native/vm/Makefile.am
src/native/vm/cldc1.1/com_sun_cldc_io_ResourceInputStream.cpp
src/native/vm/cldc1.1/com_sun_cldc_io_j2me_socket_Protocol.cpp
src/native/vm/cldc1.1/com_sun_cldchi_io_ConsoleOutputStream.cpp
src/native/vm/cldc1.1/com_sun_cldchi_jvm_JVM.cpp
src/native/vm/cldc1.1/java_lang_Class.cpp
src/native/vm/cldc1.1/java_lang_Double.cpp
src/native/vm/cldc1.1/java_lang_Float.cpp
src/native/vm/cldc1.1/java_lang_Math.cpp
src/native/vm/cldc1.1/java_lang_Object.cpp
src/native/vm/cldc1.1/java_lang_Runtime.cpp
src/native/vm/cldc1.1/java_lang_String.cpp
src/native/vm/cldc1.1/java_lang_System.cpp
src/native/vm/cldc1.1/java_lang_Thread.cpp
src/native/vm/cldc1.1/java_lang_Throwable.cpp
src/native/vm/gnuclasspath/Makefile.am
src/native/vm/gnuclasspath/gnu_classpath_VMStackWalker.cpp
src/native/vm/gnuclasspath/gnu_classpath_VMSystemProperties.cpp
src/native/vm/gnuclasspath/gnu_classpath_jdwp_VMFrame.c
src/native/vm/gnuclasspath/gnu_classpath_jdwp_VMMethod.c
src/native/vm/gnuclasspath/gnu_classpath_jdwp_VMVirtualMachine.c
src/native/vm/gnuclasspath/gnu_java_lang_VMCPStringBuilder.cpp
src/native/vm/gnuclasspath/gnu_java_lang_management_VMClassLoadingMXBeanImpl.cpp
src/native/vm/gnuclasspath/gnu_java_lang_management_VMMemoryMXBeanImpl.cpp
src/native/vm/gnuclasspath/gnu_java_lang_management_VMRuntimeMXBeanImpl.cpp
src/native/vm/gnuclasspath/gnu_java_lang_management_VMThreadMXBeanImpl.cpp
src/native/vm/gnuclasspath/java_lang_VMClass.cpp
src/native/vm/gnuclasspath/java_lang_VMClassLoader.cpp
src/native/vm/gnuclasspath/java_lang_VMObject.cpp
src/native/vm/gnuclasspath/java_lang_VMRuntime.cpp
src/native/vm/gnuclasspath/java_lang_VMString.cpp
src/native/vm/gnuclasspath/java_lang_VMSystem.cpp
src/native/vm/gnuclasspath/java_lang_VMThread.cpp
src/native/vm/gnuclasspath/java_lang_VMThrowable.cpp
src/native/vm/gnuclasspath/java_lang_management_VMManagementFactory.c [deleted file]
src/native/vm/gnuclasspath/java_lang_management_VMManagementFactory.cpp [new file with mode: 0644]
src/native/vm/gnuclasspath/java_lang_reflect_VMConstructor.cpp
src/native/vm/gnuclasspath/java_lang_reflect_VMField.cpp
src/native/vm/gnuclasspath/java_lang_reflect_VMMethod.cpp
src/native/vm/gnuclasspath/java_lang_reflect_VMProxy.c
src/native/vm/gnuclasspath/java_security_VMAccessController.cpp
src/native/vm/gnuclasspath/java_util_concurrent_atomic_AtomicLong.cpp
src/native/vm/gnuclasspath/sun_reflect_ConstantPool.cpp
src/native/vm/nativevm.c [deleted file]
src/native/vm/nativevm.cpp [new file with mode: 0644]
src/native/vm/nativevm.h [deleted file]
src/native/vm/nativevm.hpp [new file with mode: 0644]
src/native/vm/openjdk/Makefile.am
src/native/vm/openjdk/hpi.c [deleted file]
src/native/vm/openjdk/hpi.cpp [new file with mode: 0644]
src/native/vm/openjdk/hpi.h [deleted file]
src/native/vm/openjdk/hpi.hpp [new file with mode: 0644]
src/native/vm/openjdk/jvm.cpp
src/native/vm/openjdk/management.cpp [new file with mode: 0644]
src/native/vm/openjdk/management.hpp [new file with mode: 0644]
src/native/vm/reflection.cpp
src/native/vm/reflection.hpp
src/native/vm/sun_misc_Unsafe.cpp
src/threads/Makefile.am
src/threads/lock-common.h [deleted file]
src/threads/lock.cpp [new file with mode: 0644]
src/threads/lock.hpp [new file with mode: 0644]
src/threads/lockword.cpp [new file with mode: 0644]
src/threads/lockword.hpp [new file with mode: 0644]
src/threads/none/lock.h
src/threads/none/thread-none.h
src/threads/posix/Makefile.am
src/threads/posix/condition-posix.hpp
src/threads/posix/lock.c [deleted file]
src/threads/posix/lock.h [deleted file]
src/threads/posix/mutex-posix.hpp
src/threads/posix/thread-posix.cpp
src/threads/posix/thread-posix.hpp
src/threads/thread.cpp
src/threads/thread.hpp
src/threads/threadlist.c [deleted file]
src/threads/threadlist.cpp [new file with mode: 0644]
src/threads/threadlist.h [deleted file]
src/threads/threadlist.hpp [new file with mode: 0644]
src/toolbox/Makefile.am
src/toolbox/avl.h
src/toolbox/bitvector.c
src/toolbox/chain.c [deleted file]
src/toolbox/chain.h [deleted file]
src/toolbox/hashtable.c
src/toolbox/hashtable.h
src/toolbox/list.c [deleted file]
src/toolbox/list.h [deleted file]
src/toolbox/list.hpp [new file with mode: 0644]
src/toolbox/logging.h
src/toolbox/set.c
src/toolbox/tree.c [deleted file]
src/toolbox/tree.h [deleted file]
src/toolbox/util.h
src/vm/Makefile.am
src/vm/access.c
src/vm/access.h
src/vm/annotation.c
src/vm/annotation.h
src/vm/array.c [deleted file]
src/vm/array.cpp [new file with mode: 0644]
src/vm/array.h [deleted file]
src/vm/array.hpp [new file with mode: 0644]
src/vm/assertion.c [deleted file]
src/vm/assertion.cpp [new file with mode: 0644]
src/vm/assertion.h [deleted file]
src/vm/assertion.hpp [new file with mode: 0644]
src/vm/builtin.c [deleted file]
src/vm/builtin.h [deleted file]
src/vm/builtintable.inc [deleted file]
src/vm/class.c
src/vm/class.h
src/vm/classcache.c
src/vm/classcache.h
src/vm/descriptor.h
src/vm/exceptions.cpp
src/vm/exceptions.hpp
src/vm/field.c [deleted file]
src/vm/field.cpp [new file with mode: 0644]
src/vm/field.h [deleted file]
src/vm/field.hpp [new file with mode: 0644]
src/vm/finalizer.c
src/vm/global.h
src/vm/initialize.c
src/vm/javaobjects.cpp
src/vm/javaobjects.hpp
src/vm/jit/Makefile.am
src/vm/jit/abi.h
src/vm/jit/allocator/liveness.c
src/vm/jit/allocator/lsra.c
src/vm/jit/allocator/simplereg.c
src/vm/jit/allocator/simplereg.h
src/vm/jit/alpha/Makefile.am
src/vm/jit/alpha/arch.h
src/vm/jit/alpha/codegen.c
src/vm/jit/alpha/codegen.h
src/vm/jit/alpha/emit.c
src/vm/jit/alpha/linux/md-os.c
src/vm/jit/alpha/md-stubs.hpp [new file with mode: 0644]
src/vm/jit/alpha/md.c
src/vm/jit/alpha/md.h
src/vm/jit/alpha/patcher.c
src/vm/jit/argument.c [deleted file]
src/vm/jit/argument.cpp [new file with mode: 0644]
src/vm/jit/argument.h [deleted file]
src/vm/jit/argument.hpp [new file with mode: 0644]
src/vm/jit/arm/Makefile.am
src/vm/jit/arm/arch.h
src/vm/jit/arm/asmpart.S
src/vm/jit/arm/codegen.c
src/vm/jit/arm/codegen.h
src/vm/jit/arm/emit.c
src/vm/jit/arm/linux/md-os.c
src/vm/jit/arm/md-stubs.hpp [new file with mode: 0644]
src/vm/jit/arm/md.h
src/vm/jit/arm/patcher.c
src/vm/jit/asmpart.h
src/vm/jit/builtin.cpp [new file with mode: 0644]
src/vm/jit/builtin.hpp [new file with mode: 0644]
src/vm/jit/builtintable.inc [new file with mode: 0644]
src/vm/jit/cfg.c
src/vm/jit/cfg.h
src/vm/jit/code.c [deleted file]
src/vm/jit/code.cpp [new file with mode: 0644]
src/vm/jit/code.h [deleted file]
src/vm/jit/code.hpp [new file with mode: 0644]
src/vm/jit/codegen-common.c [deleted file]
src/vm/jit/codegen-common.cpp [new file with mode: 0644]
src/vm/jit/codegen-common.h [deleted file]
src/vm/jit/codegen-common.hpp [new file with mode: 0644]
src/vm/jit/disass.h
src/vm/jit/dseg.c
src/vm/jit/dseg.h
src/vm/jit/emit-common.c [deleted file]
src/vm/jit/emit-common.cpp [new file with mode: 0644]
src/vm/jit/emit-common.h [deleted file]
src/vm/jit/emit-common.hpp [new file with mode: 0644]
src/vm/jit/exceptiontable.c
src/vm/jit/exceptiontable.h
src/vm/jit/executionstate.c
src/vm/jit/executionstate.h
src/vm/jit/i386/Makefile.am
src/vm/jit/i386/arch.h
src/vm/jit/i386/codegen.c
src/vm/jit/i386/codegen.h
src/vm/jit/i386/darwin/md-os.c
src/vm/jit/i386/emit.c
src/vm/jit/i386/emit.h
src/vm/jit/i386/freebsd/md-os.c
src/vm/jit/i386/linux/md-os.c
src/vm/jit/i386/md-stubs.hpp [new file with mode: 0644]
src/vm/jit/i386/md.c
src/vm/jit/i386/md.h
src/vm/jit/i386/patcher.c
src/vm/jit/i386/solaris/md-os.c
src/vm/jit/icmdtable.inc [deleted file]
src/vm/jit/inline/inline.c
src/vm/jit/inline/inline.h
src/vm/jit/intrp/asmpart.c
src/vm/jit/intrp/codegen.c
src/vm/jit/intrp/dynamic-super.c
src/vm/jit/intrp/engine.c
src/vm/jit/intrp/intrp.h
src/vm/jit/intrp/patcher.c
src/vm/jit/ir/Makefile.am
src/vm/jit/ir/icmd.cpp [new file with mode: 0644]
src/vm/jit/ir/icmd.hpp [new file with mode: 0644]
src/vm/jit/ir/icmdtable.inc [new file with mode: 0644]
src/vm/jit/ir/instruction.cpp [new file with mode: 0644]
src/vm/jit/ir/instruction.hpp [new file with mode: 0644]
src/vm/jit/jit.c [deleted file]
src/vm/jit/jit.cpp [new file with mode: 0644]
src/vm/jit/jit.h [deleted file]
src/vm/jit/jit.hpp [new file with mode: 0644]
src/vm/jit/jitcache.cpp
src/vm/jit/jitcache.hpp
src/vm/jit/linenumbertable.c [deleted file]
src/vm/jit/linenumbertable.cpp [new file with mode: 0644]
src/vm/jit/linenumbertable.h [deleted file]
src/vm/jit/linenumbertable.hpp [new file with mode: 0644]
src/vm/jit/loop/analyze.c
src/vm/jit/loop/analyze.h
src/vm/jit/loop/graph.c
src/vm/jit/loop/loop.c
src/vm/jit/loop/loop.h
src/vm/jit/loop/tracing.c
src/vm/jit/loop/tracing.h
src/vm/jit/m68k/Makefile.am
src/vm/jit/m68k/arch.h
src/vm/jit/m68k/codegen.c
src/vm/jit/m68k/codegen.h
src/vm/jit/m68k/emit.c
src/vm/jit/m68k/emit.h
src/vm/jit/m68k/md-stubs.hpp [new file with mode: 0644]
src/vm/jit/m68k/md.h
src/vm/jit/m68k/patcher.c
src/vm/jit/mips/Makefile.am
src/vm/jit/mips/arch.h
src/vm/jit/mips/codegen.c
src/vm/jit/mips/codegen.h
src/vm/jit/mips/emit.c
src/vm/jit/mips/irix/md-os.c
src/vm/jit/mips/linux/md-os.c
src/vm/jit/mips/md-stubs.hpp [new file with mode: 0644]
src/vm/jit/mips/md-trap.h
src/vm/jit/mips/md.c
src/vm/jit/mips/patcher.c
src/vm/jit/oprofile-agent.cpp
src/vm/jit/oprofile-agent.hpp
src/vm/jit/optimizing/Makefile.am
src/vm/jit/optimizing/bytecode_escape.c
src/vm/jit/optimizing/dominators.c [deleted file]
src/vm/jit/optimizing/dominators.cpp [new file with mode: 0644]
src/vm/jit/optimizing/dominators.h [deleted file]
src/vm/jit/optimizing/dominators.hpp [new file with mode: 0644]
src/vm/jit/optimizing/escape.c
src/vm/jit/optimizing/escape.h
src/vm/jit/optimizing/graph.c
src/vm/jit/optimizing/graph.h
src/vm/jit/optimizing/ifconv.c
src/vm/jit/optimizing/ifconv.h
src/vm/jit/optimizing/lifetimes.c
src/vm/jit/optimizing/lifetimes.h
src/vm/jit/optimizing/lsra.c
src/vm/jit/optimizing/profile.c
src/vm/jit/optimizing/recompile.c [deleted file]
src/vm/jit/optimizing/recompile.h [deleted file]
src/vm/jit/optimizing/recompiler.cpp [new file with mode: 0644]
src/vm/jit/optimizing/recompiler.hpp [new file with mode: 0644]
src/vm/jit/optimizing/reorder.c
src/vm/jit/optimizing/reorder.h
src/vm/jit/optimizing/ssa.c
src/vm/jit/optimizing/ssa.h
src/vm/jit/optimizing/ssa2.c
src/vm/jit/optimizing/ssa3.c
src/vm/jit/optimizing/ssa_phi.c
src/vm/jit/optimizing/ssa_rename.c
src/vm/jit/parisc/arch.h
src/vm/jit/parse.c
src/vm/jit/parse.h
src/vm/jit/patcher-common.c [deleted file]
src/vm/jit/patcher-common.cpp [new file with mode: 0644]
src/vm/jit/patcher-common.h [deleted file]
src/vm/jit/patcher-common.hpp [new file with mode: 0644]
src/vm/jit/powerpc/Makefile.am
src/vm/jit/powerpc/arch.h
src/vm/jit/powerpc/codegen.c
src/vm/jit/powerpc/codegen.h
src/vm/jit/powerpc/darwin/md-os.c
src/vm/jit/powerpc/emit.c
src/vm/jit/powerpc/linux/md-os.c
src/vm/jit/powerpc/md-stubs.hpp [new file with mode: 0644]
src/vm/jit/powerpc/md.c
src/vm/jit/powerpc/md.h
src/vm/jit/powerpc/patcher.c
src/vm/jit/powerpc64/Makefile.am
src/vm/jit/powerpc64/arch.h
src/vm/jit/powerpc64/codegen.c
src/vm/jit/powerpc64/codegen.h
src/vm/jit/powerpc64/emit.c
src/vm/jit/powerpc64/linux/md-os.c
src/vm/jit/powerpc64/md-stubs.hpp [new file with mode: 0644]
src/vm/jit/powerpc64/md-trap.h
src/vm/jit/powerpc64/md.c
src/vm/jit/powerpc64/md.h
src/vm/jit/powerpc64/patcher.c
src/vm/jit/python.c
src/vm/jit/python.h
src/vm/jit/reg.c
src/vm/jit/reg.h
src/vm/jit/replace.c [deleted file]
src/vm/jit/replace.cpp [new file with mode: 0644]
src/vm/jit/replace.h [deleted file]
src/vm/jit/replace.hpp [new file with mode: 0644]
src/vm/jit/s390/Makefile.am
src/vm/jit/s390/arch.h
src/vm/jit/s390/codegen.c
src/vm/jit/s390/codegen.h
src/vm/jit/s390/emit.c
src/vm/jit/s390/md-abi.c
src/vm/jit/s390/md-stubs.hpp [new file with mode: 0644]
src/vm/jit/s390/md.c
src/vm/jit/s390/md.h
src/vm/jit/s390/patcher.c
src/vm/jit/show.c [deleted file]
src/vm/jit/show.cpp [new file with mode: 0644]
src/vm/jit/show.h [deleted file]
src/vm/jit/show.hpp [new file with mode: 0644]
src/vm/jit/sparc64/Makefile.am
src/vm/jit/sparc64/arch.h
src/vm/jit/sparc64/codegen.c
src/vm/jit/sparc64/codegen.h
src/vm/jit/sparc64/emit.c
src/vm/jit/sparc64/md-stubs.hpp [new file with mode: 0644]
src/vm/jit/sparc64/md.c
src/vm/jit/sparc64/md.h
src/vm/jit/sparc64/patcher.c
src/vm/jit/stack.c
src/vm/jit/stack.h
src/vm/jit/stacktrace.cpp
src/vm/jit/stacktrace.hpp
src/vm/jit/stubs.cpp [new file with mode: 0644]
src/vm/jit/stubs.hpp [new file with mode: 0644]
src/vm/jit/trace.cpp
src/vm/jit/trap.c
src/vm/jit/verify/typecheck-common.c
src/vm/jit/verify/typecheck-common.h
src/vm/jit/verify/typecheck-stackbased.c
src/vm/jit/verify/typecheck-typeinferer.c
src/vm/jit/verify/typecheck-typeinferer.h
src/vm/jit/verify/typecheck.c
src/vm/jit/verify/typecheck.h
src/vm/jit/verify/typeinfo.c
src/vm/jit/x86_64/Makefile.am
src/vm/jit/x86_64/arch.h
src/vm/jit/x86_64/codegen.c
src/vm/jit/x86_64/codegen.h
src/vm/jit/x86_64/emit.c
src/vm/jit/x86_64/emit.h
src/vm/jit/x86_64/linux/md-os.c
src/vm/jit/x86_64/md-abi.c
src/vm/jit/x86_64/md-stubs.hpp [new file with mode: 0644]
src/vm/jit/x86_64/md.c
src/vm/jit/x86_64/md.h
src/vm/jit/x86_64/patcher.c
src/vm/jit/x86_64/solaris/md-os.c
src/vm/linker.c
src/vm/linker.h
src/vm/loader.c [deleted file]
src/vm/loader.cpp [new file with mode: 0644]
src/vm/loader.h [deleted file]
src/vm/loader.hpp [new file with mode: 0644]
src/vm/method.c
src/vm/method.h
src/vm/options.c
src/vm/options.h
src/vm/os.cpp
src/vm/os.hpp
src/vm/package.cpp
src/vm/package.hpp
src/vm/primitive.cpp
src/vm/primitive.hpp
src/vm/primitivecore.c [deleted file]
src/vm/properties.c [deleted file]
src/vm/properties.cpp [new file with mode: 0644]
src/vm/properties.h [deleted file]
src/vm/properties.hpp [new file with mode: 0644]
src/vm/references.h
src/vm/resolve.c
src/vm/resolve.h
src/vm/signal.c
src/vm/signallocal.h
src/vm/stackmap.c
src/vm/stackmap.h
src/vm/statistics.c
src/vm/statistics.h
src/vm/string.cpp
src/vm/suck.c [deleted file]
src/vm/suck.cpp [new file with mode: 0644]
src/vm/suck.h [deleted file]
src/vm/suck.hpp [new file with mode: 0644]
src/vm/utf8.c
src/vm/utf8.h
src/vm/vftbl.hpp [new file with mode: 0644]
src/vm/vm.cpp
src/vm/vm.hpp
src/vm/zip.c
src/vm/zip.h
tests/regression/native/checkjni.c
tests/regression/native/test.c
tests/regression/native/testarguments.c
tests/regression/native/testgetobjectclass0.c
tests/threads/sableContention.java [new file with mode: 0644]
tests/threads/sableContention.patch [new file with mode: 0644]

index 72405f576fc4e41cd373326754c5e5ebe7e6520c..24002d4bbc24ec4430e40614fed4f8428dc113c4 100644 (file)
@@ -108,7 +108,7 @@ that contains a configuration script generated by Autoconf, under
 the same distribution terms as the rest of that program.
 
 
-* m4/{ac_prog_javac.m4,ac_prog_javac_works.m4}
+* m4/{ac_prog_jar.m4,ac_prog_javac.m4,ac_prog_javac_works.m4,ax_compiler_vendor.m4}
 
 The http://ac-archive.sourceforge.net/ website states this about the
 copyright:
index 1d19445a06b62f610f5b024841b47a121b88542a..a9572aad24d93a69bb131314587dec47abcbd850 100644 (file)
@@ -35,20 +35,7 @@ AM_CONFIG_HEADER([config.h])
 AC_PREFIX_DEFAULT(/usr/local/cacao)
 
 
-dnl Set optimization and debugging for all architectures and systems.
-if test x"$CFLAGS" = "x"; then
-    OPT_CFLAGS="-g -O0"
-else
-    OPT_CFLAGS=$CFLAGS
-fi
-
-if test x"$CXXFLAGS" = "x"; then
-    OPT_CXXFLAGS="-g -O0"
-else
-    OPT_CXXFLAGS=$CXXFLAGS
-fi
-
-dnl system type
+dnl Host CPU type.
 case "$host_cpu" in
 alpha | alphaev56 | alphapca56 )
     ARCH_DIR="alpha"
@@ -126,25 +113,22 @@ xdspcore )
     ;;
 
 * )
-    AC_MSG_ERROR($host_cpu systems are not supported at this time)
+    AC_MSG_ERROR([$host_cpu systems are currently not supported.])
     ;;
 esac
 
-dnl host type
+
+dnl Host operating system type.
 case "$host_os" in
 *cygwin* )
     OS_DIR="cygwin"
     OS_FLAGS="-D__WINDOWS__ -D__CYGWIN__"
-    CC_FLAGS="-std=c99 -pedantic -Wall -Wno-long-long"
-    CXX_FLAGS="-std=c++98 -pedantic -Wall -Wno-long-long"
     INTRP_CFLAGS="-Wall -Wno-long-long $ARCH_FLAGS $OS_FLAGS"
     ;;
 
 *darwin* )
     OS_DIR="darwin"
     OS_FLAGS="-D__DARWIN__"
-    CC_FLAGS="-std=c99 -pedantic -Wall -Wno-long-long"
-    CXX_FLAGS="-std=c++98 -pedantic -Wall -Wno-long-long"
     INTRP_CFLAGS="-Wall -Wno-long-long $ARCH_FLAGS $OS_FLAGS"
     ;;
 
@@ -152,24 +136,18 @@ dnl Must be BEFORE *freebsd*.
 *kfreebsd*-gnu)
     OS_DIR="freebsd"
     OS_FLAGS="-D__FREEBSD__ -D_POSIX_C_SOURCE=200112L -D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED -D_BSD_SOURCE"
-    CC_FLAGS="-std=c99 -pedantic -Wall -Wno-long-long"
-    CXX_FLAGS="-std=c++98 -pedantic -Wall -Wno-long-long"
     INTRP_CFLAGS="-Wall -Wno-long-long $ARCH_FLAGS $OS_FLAGS"
     ;;
 
 *freebsd* )
     OS_DIR="freebsd"
     OS_FLAGS="-D__FREEBSD__ -D_XOPEN_SOURCE_EXTENDED"
-    CC_FLAGS="-std=c99 -pedantic -Wall -Wno-long-long"
-    CXX_FLAGS="-std=c++98 -pedantic -Wall -Wno-long-long"
     INTRP_CFLAGS="-Wall -Wno-long-long $ARCH_FLAGS $OS_FLAGS"
     ;;
 
 *irix* )
     OS_DIR="irix"
     OS_FLAGS="-D__IRIX__"
-    CC_FLAGS=""
-    CXX_FLAGS=""
     INTRP_CFLAGS="$ARCH_FLAGS $OS_FLAGS"
     ;;
 
@@ -177,24 +155,18 @@ dnl Must be BEFORE *linux*.
 *uclinux | *elf )
     OS_DIR="uclinux"
     OS_FLAGS="-D__LINUX__ -D_POSIX_C_SOURCE=200112L -D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED -D_BSD_SOURCE"
-    CC_FLAGS="-std=c99 -pedantic -Wall -Wno-long-long"
-    CXX_FLAGS="-std=c++98 -pedantic -Wall -Wno-long-long"
     INTRP_CFLAGS="-Wall -Wno-long-long $ARCH_FLAGS $OS_FLAGS"
     ;;
 
 *linux* | *Linux* )
     OS_DIR="linux"
     OS_FLAGS="-D__LINUX__ -D_POSIX_C_SOURCE=200112L -D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED -D_BSD_SOURCE"
-    CC_FLAGS="-std=c99 -pedantic -Wall -Wno-long-long"
-    CXX_FLAGS="-std=c++98 -pedantic -Wall -Wno-long-long"
     INTRP_CFLAGS="-Wall -Wno-long-long $ARCH_FLAGS $OS_FLAGS"
     ;;
 
 *netbsd* )
     OS_DIR="netbsd"
     OS_FLAGS="-D__NETBSD__ -D_POSIX_C_SOURCE=200112L -D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED -D_BSD_SOURCE"
-    CC_FLAGS="-std=c99 -pedantic -Wall -Wno-long-long"
-    CXX_FLAGS="-std=c++98 -pedantic -Wall -Wno-long-long"
     INTRP_CFLAGS="-Wall -Wno-long-long $ARCH_FLAGS $OS_FLAGS"
     ;;
 
@@ -204,18 +176,62 @@ dnl Must be BEFORE *linux*.
     dnl not set when cpp is called with -std=c99, therefore we add them
     dnl here.
     OS_FLAGS="-D__SOLARIS__ -D_POSIX_C_SOURCE=200112L -D__EXTENSIONS__ -D_BSD_SOURCE"
-    CC_FLAGS="-std=c99 -pedantic -Wall -Wno-long-long -D_XOPEN_SOURCE=600"
-    CXX_FLAGS="-std=c++98 -pedantic -Wall -Wno-long-long"
+    CC_FLAGS="-D_XOPEN_SOURCE=600"
+    CXX_FLAGS="-D_XOPEN_SOURCE=500"
     INTRP_CFLAGS="-Wall -Wno-long-long $ARCH_FLAGS $OS_FLAGS"
     ;;
 
 * )
+    AC_MSG_ERROR([$host_os operating systems are currently not supported.])
     ;;
 esac
 
 
-dnl temporary set the CFLAGS for configure tests (e.g. inline keyword)
-dnl we set it properly at the end of this file
+dnl Set optimization and debugging for all architectures and systems.
+dnl NOTE: Setting the CFLAGS/CXXFLAGS only works before calling AC_PROG_CC/AC_PROG_CXX.
+if test x"$CFLAGS" = "x"; then
+    OPT_CFLAGS="-g -O0"
+else
+    OPT_CFLAGS=$CFLAGS
+fi
+
+if test x"$CXXFLAGS" = "x"; then
+    OPT_CXXFLAGS="-g -O0"
+else
+    OPT_CXXFLAGS=$CXXFLAGS
+fi
+
+dnl Check for compiler.
+AC_PROG_CC
+AC_PROG_CXX
+
+dnl Check compiler vendor.
+AX_COMPILER_VENDOR
+
+dnl Set compiler flags depending on the compiler vendor.
+case "$ax_cv_c_compiler_vendor" in
+gnu )
+    CC_FLAGS="-std=c99 -pedantic -Wall -Wno-long-long $CC_FLAGS"
+    CXX_FLAGS="-std=c++98 -pedantic -Wall -Wno-long-long $CXX_FLAGS"
+    ;;
+
+sgi )
+    CC_FLAGS="-c99 $CC_FLAGS"
+    CXX_FLAGS="$CXX_FLAGS"
+    ;;
+
+sun )
+    CC_FLAGS="-xc99 $CC_FLAGS"
+    CXX_FLAGS="$CXX_FLAGS"
+    ;;
+
+* )    
+    AC_MSG_ERROR([$ax_cv_c_compiler_vendor compilers are currently not supported.])
+    ;;
+esac
+
+dnl Temporary set the CFLAGS for configure tests (e.g. inline keyword)
+dnl we set it properly at the end of this file.
 CFLAGS="$OPT_CFLAGS $ARCH_FLAGS $OS_FLAGS $CC_FLAGS"
 CXXFLAGS="$OPT_CXXFLAGS $ARCH_FLAGS $OS_FLAGS $CXX_FLAGS"
 
@@ -230,10 +246,7 @@ AC_SUBST(JAVA_ARCH)
 AC_SUBST(OS_DIR)
 AC_SUBST(USE_SCHEDULER)
 
-
 dnl Checks for programs.
-AC_PROG_CC
-AC_PROG_CXX
 AM_PROG_AS
 AC_PROG_LD
 AC_PROG_LD_GNU
@@ -254,10 +267,12 @@ AC_CHECK_HEADERS([stdint.h],, [AC_MSG_ERROR(cannot find stdint.h)])
 dnl keep them alpha-sorted!
 AC_CHECK_HEADERS([assert.h])
 AC_CHECK_HEADERS([errno.h])
+AC_CHECK_HEADERS([execinfo.h])
 AC_CHECK_HEADERS([fcntl.h])
 AC_CHECK_HEADERS([libgen.h])
 AC_CHECK_HEADERS([netdb.h])
 AC_CHECK_HEADERS([signal.h])
+AC_CHECK_HEADERS([stdarg.h])
 AC_CHECK_HEADERS([stdint.h])
 AC_CHECK_HEADERS([stdio.h])
 AC_CHECK_HEADERS([stdlib.h])
@@ -285,7 +300,6 @@ AC_STRUCT_TM
 
 dnl Checks for libraries (NOTE: Should be done before function checks,
 dnl as some functions may be in libraries we check for).
-
 case "${OS_DIR}" in
     solaris )
          AC_CHECK_LIB([socket], [gethostname],, [AC_MSG_ERROR(cannot find libsocket)])
@@ -304,6 +318,8 @@ AC_CHECK_FUNCS([accept])
 AC_CHECK_FUNCS([access])
 AC_CHECK_FUNCS([atoi])
 AC_CHECK_FUNCS([atol])
+AC_CHECK_FUNCS([backtrace])
+AC_CHECK_FUNCS([backtrace_symbols])
 AC_CHECK_FUNCS([calloc])
 AC_CHECK_FUNCS([close])
 AC_CHECK_FUNCS([confstr])
@@ -320,6 +336,7 @@ AC_CHECK_FUNCS([fstat])
 AC_CHECK_FUNCS([fsync])
 AC_CHECK_FUNCS([ftruncate])
 AC_CHECK_FUNCS([getcwd])
+AC_CHECK_FUNCS([getenv])
 AC_CHECK_FUNCS([gethostbyname])
 AC_CHECK_FUNCS([gethostname])
 AC_CHECK_FUNCS([getpagesize])
@@ -340,6 +357,7 @@ AC_CHECK_FUNCS([memset])
 AC_CHECK_FUNCS([mmap])
 AC_CHECK_FUNCS([mprotect])
 AC_CHECK_FUNCS([open])
+AC_CHECK_FUNCS([printf])
 AC_CHECK_FUNCS([read])
 AC_CHECK_FUNCS([readlink])
 AC_CHECK_FUNCS([realloc])
@@ -355,12 +373,15 @@ AC_CHECK_FUNCS([str2sig])
 AC_CHECK_FUNCS([strcat])
 AC_CHECK_FUNCS([strchr])
 AC_CHECK_FUNCS([strcpy])
+AC_CHECK_FUNCS([strcmp])
 AC_CHECK_FUNCS([strdup])
 AC_CHECK_FUNCS([strerror])
 AC_CHECK_FUNCS([strlen])
 AC_CHECK_FUNCS([strncmp])
 AC_CHECK_FUNCS([strstr])
 AC_CHECK_FUNCS([time])
+AC_CHECK_FUNCS([va_end])
+AC_CHECK_FUNCS([va_start])
 AC_CHECK_FUNCS([write])
 
 
@@ -544,17 +565,8 @@ AC_CHECK_ENABLE_STATICVM
 AC_CHECK_ENABLE_ANNOTATIONS
 AC_CHECK_ENABLE_ASSERTION
 
-
-dnl where is CACAO's vm.zip
-AC_MSG_CHECKING(where CACAO's vm.zip is installed)
-AC_ARG_WITH([vm-zip],
-            [AS_HELP_STRING(--with-vm-zip=<path>,path to CACAO's vm.zip (includes the name of the file and may be flat) [[default=/usr/local/cacao/share/cacao/vm.zip]])],
-            [CACAO_VM_ZIP=${withval}],
-            [CACAO_VM_ZIP=${CACAO_PREFIX}/share/cacao/vm.zip])
-AC_MSG_RESULT(${CACAO_VM_ZIP})
-AC_DEFINE_UNQUOTED([CACAO_VM_ZIP], "${CACAO_VM_ZIP}", [CACAO's vm.zip])
-AC_SUBST(CACAO_VM_ZIP)
-
+dnl This one depends on AC_CHECK_ENABLE_ZLIB.
+AC_CHECK_WITH_VM_ZIP
 
 AC_CHECK_WITH_JAVA_RUNTIME_LIBRARY
 
@@ -574,11 +586,14 @@ dnl The check for jni_md.h must be before jni.h.
 AC_CHECK_WITH_JNI_MD_H
 AC_CHECK_WITH_JNI_H
 
-dnl HPI is only required for OpenJDK
+dnl JVM, HPI, and JMM is only required for OpenJDK.
 case "${WITH_JAVA_RUNTIME_LIBRARY}" in
     openjdk)
+        AC_CHECK_WITH_JVM_MD_H
+        AC_CHECK_WITH_JVM_H
         AC_CHECK_WITH_HPI_MD_H
         AC_CHECK_WITH_HPI_H
+        AC_CHECK_WITH_JMM_H
         ;;
     *)
         ;;
diff --git a/m4/ax_compiler_vendor.m4 b/m4/ax_compiler_vendor.m4
new file mode 100644 (file)
index 0000000..a1da61e
--- /dev/null
@@ -0,0 +1,33 @@
+dnl Taken from http://ac-archive.sourceforge.net/
+
+dnl @synopsis AX_COMPILER_VENDOR
+dnl
+dnl @summary find the vendor (gnu, intel, etc.) of the C/C++ compiler
+dnl
+dnl Determine the vendor of the C/C++ compiler, e.g., gnu, intel, ibm,
+dnl sun, hp, borland, comeau, dec, cray, kai, lcc, metrowerks, sgi,
+dnl microsoft, watcom, etc. The vendor is returned in the cache
+dnl variable $ax_cv_c_compiler_vendor for C and
+dnl $ax_cv_cxx_compiler_vendor for C++.
+dnl
+dnl @category C
+dnl @category Cxx
+dnl @author Steven G. Johnson <stevenj@alum.mit.edu> with Matteo Frigo
+dnl @version 2005-05-30
+dnl @license GPLWithACException
+
+AC_DEFUN([AX_COMPILER_VENDOR],
+[
+AC_CACHE_CHECK([for _AC_LANG compiler vendor], ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor,
+ [ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor=unknown
+  # note: don't check for gcc first since some other compilers define __GNUC__
+  for ventest in intel:__ICC,__ECC,__INTEL_COMPILER ibm:__xlc__,__xlC__,__IBMC__,__IBMCPP__ gnu:__GNUC__ sun:__SUNPRO_C,__SUNPRO_CC hp:__HP_cc,__HP_aCC dec:__DECC,__DECCXX,__DECC_VER,__DECCXX_VER borland:__BORLANDC__,__TURBOC__ comeau:__COMO__ cray:_CRAYC kai:__KCC lcc:__LCC__ metrowerks:__MWERKS__ sgi:__sgi,sgi microsoft:_MSC_VER watcom:__WATCOMC__ portland:__PGI; do
+    vencpp="defined("`echo $ventest | cut -d: -f2 | sed 's/,/) || defined(/g'`")"
+    AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,[
+#if !($vencpp)
+      thisisanerror;
+#endif
+])], [ax_cv_]_AC_LANG_ABBREV[_compiler_vendor=`echo $ventest | cut -d: -f1`; break])
+  done
+ ])
+])
index 1dcc4e4a84695a878f3c12d9f2300adec101c82e..5b05b1d63564f99263700114be0293be8fc030c6 100644 (file)
--- a/m4/dl.m4
+++ b/m4/dl.m4
@@ -36,7 +36,16 @@ AC_MSG_RESULT(${ENABLE_DL})
 
 if test x"${ENABLE_DL}" = "xyes"; then
     AC_CHECK_HEADERS([dlfcn.h],, [AC_MSG_ERROR(cannot find dlfcn.h)])
-    AC_CHECK_LIB([dl], [dlopen],, [AC_MSG_ERROR(cannot find libdl)])
+
+    case "${OS_DIR}" in
+        freebsd | netbsd )
+            dnl There is no libdl on FreeBSD, and NetBSD (see PR96).
+            ;;
+        *)
+            AC_CHECK_LIB([dl], [dlopen],, [AC_MSG_ERROR(cannot find libdl)])
+            ;;
+    esac
+    
     AC_CHECK_FUNCS([dlclose])
     AC_CHECK_FUNCS([dlerror])
     AC_CHECK_FUNCS([dlopen])
diff --git a/m4/jmm.m4 b/m4/jmm.m4
new file mode 100644 (file)
index 0000000..37c86ed
--- /dev/null
+++ b/m4/jmm.m4
@@ -0,0 +1,42 @@
+dnl m4/jmm.m4
+dnl
+dnl Copyright (C) 2008 Theobroma Systems Ltd.
+dnl
+dnl This file is part of CACAO.
+dnl
+dnl This program is free software; you can redistribute it and/or
+dnl modify it under the terms of the GNU General Public License as
+dnl published by the Free Software Foundation; either version 2, or (at
+dnl your option) any later version.
+dnl
+dnl This program is distributed in the hope that it will be useful, but
+dnl WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+dnl General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with this program; if not, write to the Free Software
+dnl Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+dnl 02110-1301, USA.
+
+
+dnl Check for jmm.h
+
+AC_DEFUN([AC_CHECK_WITH_JMM_H],[
+AC_MSG_CHECKING(where jmm.h is installed)
+AC_ARG_WITH([jmm_h],
+            [AS_HELP_STRING(--with-jmm_h=<dir>,path to jmm.h (only with --with-java-runtime-library=openjdk) [[default=${JAVA_RUNTIME_LIBRARY_PREFIX}/jdk/src/share/javavm/export]])],
+            [WITH_JMM_H=${withval}],
+            [case "${WITH_JAVA_RUNTIME_LIBRARY}" in
+                 openjdk)
+                     WITH_JMM_H=${JAVA_RUNTIME_LIBRARY_PREFIX}/jdk/src/share/javavm/export
+                     ;;
+                 *)
+                     ;;
+            esac])
+AC_MSG_RESULT(${WITH_JMM_H})
+
+AC_CHECK_HEADER([${WITH_JMM_H}/jmm.h],
+                [AC_DEFINE_UNQUOTED([INCLUDE_JMM_H], "${WITH_JMM_H}/jmm.h", [Java runtime library jmm.h header])],
+                [AC_MSG_ERROR(cannot find jmm.h)])
+])
diff --git a/m4/jvm.m4 b/m4/jvm.m4
new file mode 100644 (file)
index 0000000..b431497
--- /dev/null
+++ b/m4/jvm.m4
@@ -0,0 +1,67 @@
+dnl m4/jvm.m4
+dnl
+dnl Copyright (C) 2008 Theobroma Systems Ltd.
+dnl
+dnl This file is part of CACAO.
+dnl
+dnl This program is free software; you can redistribute it and/or
+dnl modify it under the terms of the GNU General Public License as
+dnl published by the Free Software Foundation; either version 2, or (at
+dnl your option) any later version.
+dnl
+dnl This program is distributed in the hope that it will be useful, but
+dnl WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+dnl General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with this program; if not, write to the Free Software
+dnl Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+dnl 02110-1301, USA.
+
+
+dnl Check for jvm_md.h
+
+AC_DEFUN([AC_CHECK_WITH_JVM_MD_H],[
+AC_MSG_CHECKING(where jvm_md.h is installed)
+AC_ARG_WITH([jvm_md_h],
+            [AS_HELP_STRING(--with-jvm_md_h=<dir>,path to jvm_md.h (only with --with-java-runtime-library=openjdk) [[default=${JAVA_RUNTIME_LIBRARY_PREFIX}/jdk/src/solaris/javavm/export]])],
+            [WITH_JVM_MD_H=${withval}],
+            [case "${WITH_JAVA_RUNTIME_LIBRARY}" in
+                 openjdk)
+                     WITH_JVM_MD_H=${JAVA_RUNTIME_LIBRARY_PREFIX}/jdk/src/solaris/javavm/export
+                     ;;
+                 *)
+                     ;;
+            esac])
+AC_MSG_RESULT(${WITH_JVM_MD_H})
+
+AC_CHECK_HEADER([${WITH_JVM_MD_H}/jvm_md.h],
+                [AC_DEFINE_UNQUOTED([INCLUDE_JVM_MD_H], "${WITH_JVM_MD_H}/jvm_md.h", [Java runtime library jvm_md.h header])],
+                [AC_MSG_ERROR(cannot find jvm_md.h)])
+
+dnl Add the path to jvm_md.h to the CPPFLAGS so jvm.h can find it.
+CPPFLAGS="${CPPFLAGS} -I${WITH_JVM_MD_H}"
+])
+
+
+dnl Check for jvm.h
+
+AC_DEFUN([AC_CHECK_WITH_JVM_H],[
+AC_MSG_CHECKING(where jvm.h is installed)
+AC_ARG_WITH([jvm_h],
+            [AS_HELP_STRING(--with-jvm_h=<dir>,path to jvm.h (only with --with-java-runtime-library=openjdk) [[default=${JAVA_RUNTIME_LIBRARY_PREFIX}/jdk/src/share/javavm/export]])],
+            [WITH_JVM_H=${withval}],
+            [case "${WITH_JAVA_RUNTIME_LIBRARY}" in
+                 openjdk)
+                     WITH_JVM_H=${JAVA_RUNTIME_LIBRARY_PREFIX}/jdk/src/share/javavm/export
+                     ;;
+                 *)
+                     ;;
+            esac])
+AC_MSG_RESULT(${WITH_JVM_H})
+
+AC_CHECK_HEADER([${WITH_JVM_H}/jvm.h],
+                [AC_DEFINE_UNQUOTED([INCLUDE_JVM_H], "${WITH_JVM_H}/jvm.h", [Java runtime library jvm.h header])],
+                [AC_MSG_ERROR(cannot find jvm.h)])
+])
diff --git a/m4/vm-zip.m4 b/m4/vm-zip.m4
new file mode 100644 (file)
index 0000000..85f2548
--- /dev/null
@@ -0,0 +1,43 @@
+dnl m4/vm-zip.m4
+dnl
+dnl Copyright (C) 2008
+dnl CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+dnl 
+dnl This file is part of CACAO.
+dnl 
+dnl This program is free software; you can redistribute it and/or
+dnl modify it under the terms of the GNU General Public License as
+dnl published by the Free Software Foundation; either version 2, or (at
+dnl your option) any later version.
+dnl 
+dnl This program is distributed in the hope that it will be useful, but
+dnl WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+dnl General Public License for more details.
+dnl 
+dnl You should have received a copy of the GNU General Public License
+dnl along with this program; if not, write to the Free Software
+dnl Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+dnl 02110-1301, USA.
+
+
+dnl where is CACAO's vm.zip
+
+AC_DEFUN([AC_CHECK_WITH_VM_ZIP],[
+AC_MSG_CHECKING(where CACAO's vm.zip is installed)
+AC_ARG_WITH([vm-zip],
+            [AS_HELP_STRING(--with-vm-zip=<path>,path to CACAO's vm.zip (includes the name of the file and may be flat) [[default=(--enable-zlib:${CACAO_PREFIX}/share/cacao/vm.zip,--disable-zlib:${CACAO_PREFIX}/share/cacao/classes)]])],
+            [CACAO_VM_ZIP=${withval}],
+            [case "${ENABLE_ZLIB}" in
+                 no)
+                     CACAO_VM_ZIP=${CACAO_PREFIX}/share/cacao/classes
+                     ;;
+                 *)
+                     CACAO_VM_ZIP=${CACAO_PREFIX}/share/cacao/vm.zip
+                     ;;
+             esac
+            ])
+AC_MSG_RESULT(${CACAO_VM_ZIP})
+AC_DEFINE_UNQUOTED([CACAO_VM_ZIP], "${CACAO_VM_ZIP}", [CACAO's vm.zip])
+AC_SUBST(CACAO_VM_ZIP)
+])
index e1ad4163029fe24410628285018e08b20d39e622..9bf7c0588469488b08f0d89c3e38cb604f1b8582 100644 (file)
 
 #include "config.h"
 
-#include <assert.h>
-
 #if defined(ENABLE_JRE_LAYOUT)
 # include <errno.h>
 # include <libgen.h>
 # include <unistd.h>
 #endif
 
+#include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
 
-#include "vm/types.h"
-
-#include "native/jni.h"
-#include "native/native.h"
+#include "native/jni.hpp"
+#include "native/native.hpp"
 
 #if defined(ENABLE_JVMTI)
 # include "native/jvmti/jvmti.h"
@@ -83,17 +80,12 @@ int main(int argc, char **argv)
        void*       libjvm_vm_run;
        const char* lterror;
 
-       bool (*VM_create)(JavaVM **, void **, void *);
-       void (*vm_run)(JavaVM *, JavaVMInitArgs *);
+       bool (*VM_create)(JavaVM**, void**, void*);
+       void (*vm_run)(JavaVM*, JavaVMInitArgs*);
 #endif
 
-       JavaVM         *vm;                 /* denotes a Java VM                  */
-       JNIEnv         *env;
-       JavaVMInitArgs *vm_args;
-
-       /* prepare the options */
-
-       vm_args = prepare_options(argc, argv);
+       // Prepare the options.
+       JavaVMInitArgs* vm_args = prepare_options(argc, argv);
        
        /* load and initialize a Java VM, return a JNI interface pointer in env */
 
@@ -118,7 +110,7 @@ int main(int argc, char **argv)
                os::abort();
        }
 
-       /* concatinate the library name */
+       /* concatenate the library name */
 
        strcat(path, "/../lib/"LIBJVM_NAME);
 # else
@@ -148,9 +140,8 @@ int main(int argc, char **argv)
                        os::abort();
                }
 
-               /* free the error string */
-
-               free((void *) lterror);
+               // Free the error string.
+               os::free((void*) lterror);
        }
 
        libjvm_VM_create = os::dlsym(libjvm_handle, "VM_create");
@@ -160,13 +151,14 @@ int main(int argc, char **argv)
                os::abort();
        }
 
-       VM_create =
-               (bool (*)(JavaVM **, void **, void *)) (ptrint) libjvm_VM_create;
+       VM_create = (bool (*)(JavaVM**, void**, void*)) (uintptr_t) libjvm_VM_create;
 #endif
 
-       /* create the Java VM */
+       // Create the Java VM.
+       JavaVM* vm;
+       void*   env; // We use a void* instead of a JNIEnv* here to prevent a compiler warning.
 
-       (void) VM_create(&vm, (void**) &env, vm_args);
+       (void) VM_create(&vm, &env, vm_args);
 
 #if defined(ENABLE_JVMTI)
 # error This should be a JVMTI function.
@@ -182,15 +174,13 @@ int main(int argc, char **argv)
                os::abort();
        }
 
-       vm_run = (void (*)(JavaVM *, JavaVMInitArgs *)) (ptrint) libjvm_vm_run;
+       vm_run = (void (*)(JavaVM*, JavaVMInitArgs*)) (uintptr_t) libjvm_vm_run;
 #endif
 
-       /* run the VM */
-
+       // Run the VM.
        vm_run(vm, vm_args);
 
-       /* keep compiler happy */
-
+       // Keep compiler happy.
        return 0;
 }
 
index 9ddec49705cbcf2cbc404f6813ea5087afdc1507..507eb39d6505d023d41cc5d03f575d8cf03cb448 100644 (file)
@@ -77,7 +77,7 @@ endif
 if ENABLE_ZLIB
 pkgdata_DATA = vm.zip
 else
-pkgdata_DATA = nozip
+noinst_DATA = nozip
 endif
 endif
 
@@ -88,7 +88,7 @@ VM_JAVA_FILES = \
 if ENABLE_ZLIB
 pkgdata_DATA = vm.zip
 else
-pkgdata_DATA = nozip
+noinst_DATA = nozip
 endif
 endif
 
@@ -107,6 +107,14 @@ else
 nozip: $(VM_JAVA_FILES)
        $(mkdir_p) classes
        $(JAVAC) -bootclasspath $(BOOTCLASSPATH) -source 1.5 -target 1.5 -d classes $(VM_JAVA_FILES)
+
+install-data-local: nozip
+       $(mkinstalldirs) $(DESTDIR)$(pkgdatadir)
+       cp -R classes $(DESTDIR)$(pkgdatadir)
+
+uninstall-local:
+       rm -rf $(DESTDIR)$(pkgdatadir)/classes
+
 endif
 
 clean-local:
index 203d919442b844119de43cc4ea731f9e745c9938..78ba758a196f5adfac2e806460f21703cdb2482e 100644 (file)
@@ -59,8 +59,8 @@ noinst_LTLIBRARIES = \
 libmm_la_SOURCES = \
        codememory.c \
        codememory.h \
-       dumpmemory.c \
-       dumpmemory.h \
+       dumpmemory.cpp \
+       dumpmemory.hpp \
        $(GC_FILE) \
        gc.hpp \
        memory.c \
index e09309f843e9c55c877f71935e83ada3c7515165..ebafe09b0e8aaaa1051a3bf8b4dd928a8f7f5995 100644 (file)
@@ -29,7 +29,7 @@
 #include "config.h"
 #include "vm/types.h"
 
-#include "toolbox/list.h"
+#include "toolbox/list.hpp"
 #include "vm/method.h"
 
 
index 4362d85f58e288919c750db9c80655cb5a254491..e9fd6d50f66e34a5f5232eff0da07d1cb7bcaf71 100644 (file)
@@ -30,7 +30,7 @@
 
 #include "vm/types.h"
 
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
 #include "threads/thread.hpp"
 
 #include "compact.h"
index fd42e44a40f34d409f6d25ded778a32b217996fc..082d8083d6e225f263e92f29fe2a12fe67bd18a3 100644 (file)
@@ -37,8 +37,8 @@
 
 #include "threads/thread.hpp"
 
-#include "toolbox/list.h"
-#include "vm/jit/replace.h"
+#include "toolbox/list.hpp"
+#include "vm/jit/replace.hpp"
 
 
 /* Configuration Switches *****************************************************/
index f3630c7a3b1d8963db94b7703bcbe89700905fbc..22ce0691738fe9c8f42399c8e1be3bd1964972dc 100644 (file)
@@ -26,7 +26,7 @@
 #include "config.h"
 #include "vm/types.h"
 
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
 
 #include "gc.h"
 #include "final.h"
index f53613a363098292e9a7702d3276b1b9004adf6b..7e76976c3ebf2ccab9403c5974df39dda4fa5952 100644 (file)
@@ -32,7 +32,7 @@
 
 #include "gc.h"
 #include "region.h"
-#include "vm/array.h" /* needed for ARRAYTYPE_OBJECT */
+#include "vm/array.hpp" /* needed for ARRAYTYPE_OBJECT */
 
 
 #define GC_SIZE_DUMMY 0xff
index fe3253579640d3797d90d0761ed45946c3d9c869..7761fa8089b0050309df666fa9c841c577b7058a 100644 (file)
@@ -38,7 +38,7 @@
 #include "toolbox/logging.h"
 
 #include "vm/global.h"
-#include "vm/jit/replace.h"
+#include "vm/jit/replace.hpp"
 #include "vm/jit/stacktrace.hpp"
 
 
index 5b0dc52b824d30ffbf50a8fa4d82096609a9040f..9267d7fdb791f9975b1c946e54e6bf58a27c9f81 100644 (file)
@@ -35,7 +35,7 @@ typedef struct rootset_t rootset_t;
 
 #include "vm/method.h"
 
-#include "vm/jit/replace.h"
+#include "vm/jit/replace.hpp"
 
 
 /* Structures *****************************************************************/
index 1e0c095466a33789195590b8698a28d9ce4a8456..b56179221b9333c55b51f6423befe5654043ae84 100644 (file)
@@ -29,7 +29,7 @@
 #include <stdlib.h>
 #include <sys/mman.h> /* REMOVEME */
 
-#include "threads/lock-common.h"
+#include "threads/mutex.hpp"
 #include "threads/thread.hpp"
 
 #include "mm/codememory.h"
 #define DEFAULT_CODE_MEMORY_SIZE    128 * 1024 /* defaulting to 128kB         */
 
 #if defined(ENABLE_THREADS)
-static java_object_t *lock_code_memory = NULL;
+static Mutex *code_memory_mutex = NULL;
 #endif
-static void          *code_memory      = NULL;
-static int            code_memory_size = 0;
-static int            pagesize         = 0;
+static void  *code_memory       = NULL;
+static int    code_memory_size  = 0;
+static int    pagesize          = 0;
 
 
 /* codememory_init *************************************************************
@@ -67,11 +67,9 @@ void codememory_init(void)
        TRACESUBSYSTEMINITIALIZATION("codememory_init");
 
 #if defined(ENABLE_THREADS)
-       /* create lock for code memory */
+       /* create mutex for code memory */
 
-       lock_code_memory = NEW(java_object_t);
-
-       lock_init_object_lock(lock_code_memory);
+       code_memory_mutex = Mutex_new();
 #endif
 
        /* Get the pagesize of this architecture. */
@@ -91,7 +89,7 @@ void *codememory_get(size_t size)
 {
        void *p;
 
-       LOCK_MONITOR_ENTER(lock_code_memory);
+       Mutex_lock(code_memory_mutex);
 
        size = MEMORY_ALIGN(size, ALIGNSIZE);
 
@@ -138,7 +136,7 @@ void *codememory_get(size_t size)
        code_memory       = (void *) ((ptrint) code_memory + size);
        code_memory_size -= size;
 
-       LOCK_MONITOR_EXIT(lock_code_memory);
+       Mutex_unlock(code_memory_mutex);
 
        return p;
 }
diff --git a/src/mm/dumpmemory.c b/src/mm/dumpmemory.c
deleted file mode 100644 (file)
index 943a9c6..0000000
+++ /dev/null
@@ -1,481 +0,0 @@
-/* src/mm/dumpmemory.c - dump memory management
-
-   Copyright (C) 1996-2005, 2006, 2007, 2008
-   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
-
-   This file is part of CACAO.
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2, or (at
-   your option) any later version.
-
-   This program is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-   02110-1301, USA.
-
-*/
-
-
-#include "config.h"
-
-#include <stdint.h>
-
-#include "mm/dumpmemory.h"
-#include "mm/memory.h"
-
-#include "threads/thread.hpp"
-
-#include "vm/options.h"
-#include "vm/os.hpp"
-
-#if defined(ENABLE_STATISTICS)
-# include "vm/statistics.h"
-#endif
-
-#include "vm/vm.hpp"
-
-
-/*******************************************************************************
-
-  This structure is used for dump memory allocation if cacao
-  runs without threads.
-
-*******************************************************************************/
-
-#if !defined(ENABLE_THREADS)
-static dumpinfo_t _no_threads_dumpinfo;
-#endif
-
-#if defined(ENABLE_THREADS)
-#define DUMPINFO    &((threadobject *) THREADOBJECT)->dumpinfo
-#else
-#define DUMPINFO    &_no_threads_dumpinfo
-#endif
-
-
-/* dump_check_canaries *********************************************************
-
-   Check canaries in dump memory.
-
-   IN:
-      di...........dumpinfo_t * of the dump area to check
-         bottomsize...dump size down to which the dump area should be checked
-                      (specify 0 to check the whole dump area)
-
-   ERROR HANDLING:
-      If any canary has been changed, this function aborts the VM with
-         an error message.
-
-*******************************************************************************/
-
-#if defined(ENABLE_MEMCHECK)
-static void dump_check_canaries(dumpinfo_t *di, s4 bottomsize)
-{
-       dump_allocation_t *da;
-       uint8_t           *pm;
-       int                i, j;
-
-       /* iterate over all dump memory allocations above bottomsize */
-
-       da = di->allocations;
-
-       while (da && da->used >= bottomsize) {
-               /* check canaries */
-
-               pm = ((uint8_t *) da->mem) - MEMORY_CANARY_SIZE;
-
-               for (i = 0; i < MEMORY_CANARY_SIZE; ++i) {
-                       if (pm[i] != i + MEMORY_CANARY_FIRST_BYTE) {
-                               fprintf(stderr, "canary bytes:");
-
-                               for (j = 0; j < MEMORY_CANARY_SIZE; ++j)
-                                       fprintf(stderr, " %02x", pm[j]);
-
-                               fprintf(stderr,"\n");
-
-                               vm_abort("error: dump memory bottom canary killed: "
-                                                "%p (%d bytes allocated at %p)\n",
-                                                pm + i, da->size, da->mem);
-                       }
-               }
-
-               pm = ((uint8_t *) da->mem) + da->size;
-
-               for (i = 0; i < MEMORY_CANARY_SIZE; ++i) {
-                       if (pm[i] != i + MEMORY_CANARY_FIRST_BYTE) {
-                               fprintf(stderr, "canary bytes:");
-
-                               for (j = 0; j < MEMORY_CANARY_SIZE; ++j)
-                                       fprintf(stderr, " %02x", pm[j]);
-
-                               fprintf(stderr, "\n");
-
-                               vm_abort("error: dump memory top canary killed: "
-                                                "%p (%d bytes allocated at %p)\n",
-                                                pm + i, da->size, da->mem);
-                       }
-               }
-
-               da = da->next;
-       }
-}
-#endif /* defined(ENABLE_MEMCHECK) */
-
-
-/* dumpmemory_alloc ************************************************************
-
-   ATTENTION: This function must only be called from dumpmemory_get!
-
-   Allocate a new dump memory block.
-
-   IN:
-      di ..... dumpinfo_t of the current thread
-      size ... required memory size
-
-*******************************************************************************/
-
-void dumpmemory_alloc(dumpinfo_t *di, size_t size)
-{
-       dumpblock_t *db;
-       size_t       newblocksize;
-
-       /* Allocate a new dumpblock_t structure. */
-
-       db = memory_checked_alloc(sizeof(dumpblock_t));
-
-       /* If requested size is greater than the default, make the new
-          dump block as big as the size requested. Else use the default
-          size. */
-
-       if (size > DUMPBLOCKSIZE) {
-               newblocksize = size;
-       }
-       else {
-               newblocksize = DUMPBLOCKSIZE;
-       }
-
-       /* allocate dumpblock memory */
-
-       db->dumpmem = memory_checked_alloc(newblocksize);
-
-       db->size  = newblocksize;
-       db->prev  = di->block;
-       di->block = db;
-
-       /* Used dump size is previously allocated dump size, because the
-          remaining free memory of the previous dump block cannot be
-          used. */
-
-       di->used = di->allocated;
-
-       /* Increase the allocated dump size by the size of the new dump
-          block. */
-
-       di->allocated += newblocksize;
-
-#if defined(ENABLE_STATISTICS)
-       /* The amount of globally allocated dump memory (thread save). */
-
-       if (opt_stat)
-               globalallocateddumpsize += newblocksize;
-#endif
-}
-
-
-/* dumpmemory_get **************************************************************
-
-   Allocate memory in the dump area.
-
-   IN:
-      size.........size of block to allocate, in bytes
-                                  may be zero, in which case NULL is returned
-
-   RETURN VALUE:
-      pointer to allocated memory, or
-         NULL iff `size` was zero
-
-   ERROR HANDLING:
-      XXX This function uses `memory_checked_alloc`, which *exits* if
-         no memory could be allocated.
-
-   THREADS:
-      dumpmemory_get is thread safe. Each thread has its own dump
-      memory area.
-
-   This function is a fast allocator suitable for scratch memory that
-   can be collectively freed when the current activity (eg. compiling)
-   is done.
-
-   You cannot selectively free dump memory. Before you start
-   allocating it, you remember the current size returned by
-   `dumpmemory_marker`. Later, when you no longer need the memory,
-   call `dumpmemory_release` with the remembered size and all dump
-   memory allocated since the call to `dumpmemory_marker` will be
-   freed.
-
-*******************************************************************************/
-
-void *dumpmemory_get(size_t size)
-{
-#if defined(DISABLE_DUMP)
-
-       /* use malloc memory for dump memory (for debugging only!) */
-
-       return mem_alloc(size);
-
-#else /* !defined(DISABLE_DUMP) */
-
-       void       *p;
-       dumpinfo_t *di;
-#if defined(ENABLE_MEMCHECK)
-       s4          origsize = size; /* needed for the canary system */
-#endif
-
-       di = DUMPINFO;
-
-       if (size == 0)
-               return NULL;
-
-#if defined(ENABLE_MEMCHECK)
-       size += 2 * MEMORY_CANARY_SIZE;
-#endif
-
-       size = MEMORY_ALIGN(size, ALIGNSIZE);
-
-       /* Check if we have enough memory in the current memory block. */
-
-       if (di->used + size > di->allocated) {
-               /* If not, allocate a new one. */
-
-               dumpmemory_alloc(di, size);
-       }
-
-       /* current dump block base address + the size of the current dump
-          block - the size of the unused memory = new start address  */
-
-       p = ((uint8_t *) di->block->dumpmem) + di->block->size -
-               (di->allocated - di->used);
-
-#if defined(ENABLE_MEMCHECK)
-       {
-               dump_allocation_t *da = NEW(dump_allocation_t);
-               uint8_t           *pm;
-               int                i;
-
-               /* add the allocation to our linked list of allocations */
-
-               da->next = di->allocations;
-               da->mem  = ((uint8_t *) p) + MEMORY_CANARY_SIZE;
-               da->size = origsize;
-               da->used = di->used;
-
-               di->allocations = da;
-
-               /* write the canaries */
-
-               pm = (uint8_t *) p;
-
-               for (i = 0; i < MEMORY_CANARY_SIZE; ++i)
-                       pm[i] = i + MEMORY_CANARY_FIRST_BYTE;
-
-               pm = ((uint8_t *) da->mem) + da->size;
-
-               for (i = 0; i < MEMORY_CANARY_SIZE; ++i)
-                       pm[i] = i + MEMORY_CANARY_FIRST_BYTE;
-
-               /* make m point after the bottom canary */
-
-               p = ((uint8_t *) p) + MEMORY_CANARY_SIZE;
-
-               /* clear the memory */
-
-               (void) os_memset(p, MEMORY_CLEAR_BYTE, da->size);
-       }
-#endif /* defined(ENABLE_MEMCHECK) */
-
-       /* Increase used dump size by the allocated memory size. */
-
-       di->used += size;
-
-#if defined(ENABLE_STATISTICS)
-       if (opt_stat)
-               if (di->used > maxdumpsize)
-                       maxdumpsize = di->used;
-#endif
-
-       return p;
-
-#endif /* defined(DISABLE_DUMP) */
-}
-
-
-/* dumpmemory_realloc **********************************************************
-
-   Stupid realloc implementation for dump memory. Avoid, if possible.
-
-*******************************************************************************/
-
-void *dumpmemory_realloc(void *src, s4 len1, s4 len2)
-{
-#if defined(DISABLE_DUMP)
-       /* use malloc memory for dump memory (for debugging only!) */
-
-       return mem_realloc(src, len1, len2);
-#else
-       void *dst;
-
-       dst = dumpmemory_get(len2);
-
-       (void) os_memcpy(dst, src, len1);
-
-#if defined(ENABLE_MEMCHECK)
-       /* destroy the source */
-
-       (void) os_memset(src, MEMORY_CLEAR_BYTE, len1);
-#endif
-
-       return dst;
-#endif
-}
-
-
-/* dumpmemory_release **********************************************************
-
-   Release dump memory above the given size.
-
-   IN:
-       size........All dump memory above this mark will be freed. Usually
-                      `size` will be the return value of a `dumpmemory_marker`
-                                  call made earlier.
-
-       ERROR HANDLING:
-          XXX If the given size is invalid, this function *exits* with an
-              error message.
-                                  
-       See `dump_alloc`.
-
-*******************************************************************************/
-
-void dumpmemory_release(s4 size)
-{
-#if defined(DISABLE_DUMP)
-
-       /* use malloc memory for dump memory (for debugging only!) */
-
-       /* do nothing */
-
-#else /* !defined(DISABLE_DUMP) */
-
-       dumpinfo_t *di;
-
-       di = DUMPINFO;
-
-       if ((size < 0) || (size > di->used))
-               vm_abort("dump_release: Illegal dump release size: %d", size);
-
-#if defined(ENABLE_MEMCHECK)
-       {
-               dump_allocation_t *da, *next;
-
-               /* check canaries */
-
-               dump_check_canaries(di, size);
-
-               /* iterate over all dump memory allocations about to be released */
-
-               da = di->allocations;
-
-               while ((da != NULL) && (da->used >= size)) {
-                       next = da->next;
-
-                       /* invalidate the freed memory */
-
-                       (void) os_memset(da->mem, MEMORY_CLEAR_BYTE, da->size);
-
-                       FREE(da, dump_allocation_t);
-
-                       da = next;
-               }
-               di->allocations = da;
-       }
-#endif /* defined(ENABLE_MEMCHECK) */
-
-       /* Reset the used dump size to the size specified. */
-
-       di->used = size;
-
-       while ((di->block != NULL) && di->allocated - di->block->size >= di->used) {
-               dumpblock_t *tmp = di->block;
-
-               di->allocated -= tmp->size;
-               di->block      = tmp->prev;
-
-#if defined(ENABLE_STATISTICS)
-               /* the amount of globally allocated dump memory (thread save) */
-
-               if (opt_stat)
-                       globalallocateddumpsize -= tmp->size;
-#endif
-
-               /* Release the dump memory and the dumpinfo structure. */
-
-               os_free(tmp->dumpmem);
-               os_free(tmp);
-       }
-
-#endif /* defined(DISABLE_DUMP) */
-}
-
-
-/* dumpmemory_marker ***********************************************************
-
-   Returns a marker of the dump memory area.  This marker is actually
-   the used size of the dump memory area.
-
-   RETURN VALUE:
-       marker of the current dump memory status
-
-*******************************************************************************/
-
-int32_t dumpmemory_marker(void)
-{
-#if defined(DISABLE_DUMP)
-       /* use malloc memory for dump memory (for debugging only!) */
-
-       return 0;
-
-#else /* !defined(DISABLE_DUMP) */
-
-       dumpinfo_t *di;
-
-       di = DUMPINFO;
-
-       if (di == NULL)
-               return 0;
-
-       return di->used;
-
-#endif /* defined(DISABLE_DUMP) */
-}
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
diff --git a/src/mm/dumpmemory.cpp b/src/mm/dumpmemory.cpp
new file mode 100644 (file)
index 0000000..4650d52
--- /dev/null
@@ -0,0 +1,318 @@
+/* src/mm/dumpmemory.cpp - dump memory management
+
+   Copyright (C) 1996-2005, 2006, 2007, 2008
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+   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 "mm/dumpmemory.hpp"
+#include "mm/memory.h"
+
+#include "threads/thread.hpp"
+
+#include "vm/options.h"
+#include "vm/os.hpp"
+
+#if defined(ENABLE_STATISTICS)
+# include "vm/statistics.h"
+#endif
+
+#include "vm/vm.hpp"
+
+
+/*******************************************************************************
+
+  This structure is used for dump memory allocation if cacao
+  runs without threads.
+
+*******************************************************************************/
+
+#if !defined(ENABLE_THREADS)
+static dumpinfo_t _no_threads_dumpinfo;
+#endif
+
+
+/**
+ * Allocate a new thread-local dump memory structure.
+ */
+DumpMemory::DumpMemory() : _size(0), _used(0)
+{
+}
+
+
+/**
+ * Stupid realloc implementation for dump memory.  Avoid, if possible.
+ */
+void* DumpMemory::reallocate(void* src, size_t len1, size_t len2)
+{
+       void* dst = allocate(len2);
+
+       (void) os::memcpy(dst, src, len1);
+
+#if defined(ENABLE_MEMCHECK)
+       // Destroy the source.
+       (void) os::memset(src, MEMORY_CLEAR_BYTE, len1);
+#endif
+
+       return dst;
+}
+
+
+/**
+ * Add the given dump area to the area list.
+ *
+ * @param dm Pointer to dump area.
+ */
+void DumpMemory::add_area(DumpMemoryArea* dma)
+{
+       _areas.push_back(dma);
+
+       // Increase the size count of the dump memory.
+       _size += dma->get_size();
+
+#if defined(ENABLE_STATISTICS)
+       if (opt_stat) {
+               if (_size > (size_t) maxdumpsize)
+                       maxdumpsize = _size;
+       }
+#endif
+}
+
+
+/**
+ * Remove the given dump area from the area list.
+ *
+ * @param dm Pointer to dump area.
+ */
+void DumpMemory::remove_area(DumpMemoryArea* dma)
+{
+       // Sanity check.
+       assert(_areas.back() == dma);
+
+       // Remove the last area from the list.  The check above guarantees
+       // we are removing the correct area.
+       _areas.pop_back();
+
+       // Decrease the size and used count.
+       _size -= dma->get_size();
+       _used -= dma->get_used();
+}
+
+
+/**
+ * Allocate a new dump memory area.
+ *
+ * @ param size Required memory size.
+ */
+DumpMemoryArea::DumpMemoryArea(size_t size) : _size(0), _used(0)
+{
+       // Get the DumpMemory object of the current thread.
+       DumpMemory* dm = DumpMemory::get_current();
+
+       // Add this area to the areas list.
+       dm->add_area(this);
+}
+
+
+/**
+ * Release all dump memory blocks in the current dump area.
+ */
+DumpMemoryArea::~DumpMemoryArea()
+{
+       // Get the DumpMemory object of the current thread.
+       DumpMemory* dm = DumpMemory::get_current();
+
+#if defined(ENABLE_MEMCHECK)
+       // Check canaries.
+
+       check_canaries();
+
+       // Iterate over all dump memory allocations about to be released.
+
+       for (std::vector<DumpMemoryAllocation*>::iterator it = _allocs.begin(); it != _allocs.end(); it++) {
+               DumpMemoryAllocation* dma = *it;
+
+               // Invalidate the freed memory.
+               (void) os::memset(dma->get_mem(), MEMORY_CLEAR_BYTE, dma->get_size());
+
+               // Call the destructor of the current allocation.
+               delete dma;
+       }
+#endif /* defined(ENABLE_MEMCHECK) */
+
+       // Free all memory blocks.
+       for (std::vector<DumpMemoryBlock*>::iterator it = _blocks.begin(); it != _blocks.end(); it++) {
+               // Call the destructor of the current block.
+               delete *it;
+       }
+
+       // Remove this area for the area list.
+       dm->remove_area(this);
+}
+
+
+/**
+ * Allocate a dump memory block for the current dump memory area.
+ *
+ * @param size Required memory size.
+ *
+ * @return Pointer to the newly allocated block.
+ */
+DumpMemoryBlock* DumpMemoryArea::allocate_new_block(size_t size)
+{
+       DumpMemoryBlock* dmb = new DumpMemoryBlock(size);
+       _blocks.push_back(dmb);
+
+#if defined(ENABLE_STATISTICS)
+       if (opt_stat) {
+               DumpMemory* dm = DumpMemory::get_current();
+               dm->add_size(dmb->get_size());
+
+               if (dm->get_size() > (size_t) maxdumpsize)
+                       maxdumpsize = dm->get_size();
+       }
+#endif
+
+       return dmb;
+}
+
+
+/**
+ * Checks canaries in this dump memory area. If any canary has been changed,
+ * this function aborts the VM with an error message.
+ */
+#if defined(ENABLE_MEMCHECK)
+void DumpMemoryArea::check_canaries()
+{
+       uint8_t* pm;
+
+       // Iterate over all dump memory allocations.
+
+       for (std::vector<DumpMemoryAllocation*>::iterator it = _allocs.begin(); it != _allocs.end(); it++) {
+               DumpMemoryAllocation* dma = *it;
+
+               // Check canaries.
+
+               pm = ((uint8_t *) dma->get_mem()) - MEMORY_CANARY_SIZE;
+
+               for (int i = 0; i < MEMORY_CANARY_SIZE; ++i) {
+                       if (pm[i] != i + MEMORY_CANARY_FIRST_BYTE) {
+                               fprintf(stderr, "canary bytes:");
+
+                               for (int j = 0; j < MEMORY_CANARY_SIZE; ++j)
+                                       fprintf(stderr, " %02x", pm[j]);
+
+                               fprintf(stderr,"\n");
+
+                               vm_abort("error: dump memory bottom canary killed: "
+                                                "%p (%d bytes allocated at %p)\n",
+                                                pm + i, dma->get_size(), dma->get_mem());
+                       }
+               }
+
+               pm = ((uint8_t *) dma->get_mem()) + dma->get_size();
+
+               for (int i = 0; i < MEMORY_CANARY_SIZE; ++i) {
+                       if (pm[i] != i + MEMORY_CANARY_FIRST_BYTE) {
+                               fprintf(stderr, "canary bytes:");
+
+                               for (int j = 0; j < MEMORY_CANARY_SIZE; ++j)
+                                       fprintf(stderr, " %02x", pm[j]);
+
+                               fprintf(stderr, "\n");
+
+                               vm_abort("error: dump memory top canary killed: "
+                                                "%p (%d bytes allocated at %p)\n",
+                                                pm + i, dma->get_size(), dma->get_mem());
+                       }
+               }
+       }
+}
+#endif /* defined(ENABLE_MEMCHECK) */
+
+
+/**
+ * Allocate a memory block for the current dump memory block.
+ *
+ * @param size Required memory size.
+ */
+DumpMemoryBlock::DumpMemoryBlock(size_t size) : _size(0), _used(0), _block(0)
+{
+       // If requested size is greater than the default, make the new
+       // memory block as big as the requested size.  Otherwise use the
+       // default size.
+       _size = (size > DEFAULT_SIZE) ? size : DEFAULT_SIZE;
+
+       // Allocate a memory block.
+       _block = memory_checked_alloc(_size);
+
+#if defined(ENABLE_STATISTICS)
+       // The amount of globally allocated dump memory (thread safe).
+       if (opt_stat)
+               globalallocateddumpsize += _size;
+#endif
+}
+
+
+/**
+ * Release the memory block for the dump memory block.
+ *
+ * @param size Required memory size.
+ */
+DumpMemoryBlock::~DumpMemoryBlock()
+{
+       // Release the memory block.
+       mem_free(_block, /* XXX */ 1);
+
+#if defined(ENABLE_STATISTICS)
+       // The amount of globally allocated dump memory (thread safe).
+       if (opt_stat)
+               globalallocateddumpsize -= _size;
+#endif
+}
+
+
+// Legacy C interface.
+
+extern "C" {
+       void* DumpMemory_allocate(size_t size) { return DumpMemory::allocate(size); }
+       void* DumpMemory_reallocate(void* src, size_t len1, size_t len2) { return DumpMemory::reallocate(src, len1, len2); }
+}
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
diff --git a/src/mm/dumpmemory.h b/src/mm/dumpmemory.h
deleted file mode 100644 (file)
index 54fdb6a..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-/* src/mm/dumpmemory.h - dump memory management
-
-   Copyright (C) 1996-2005, 2006, 2007, 2008
-   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
-
-   This file is part of CACAO.
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2, or (at
-   your option) any later version.
-
-   This program is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-   02110-1301, USA.
-
-*/
-
-
-#ifndef _DUMPMEMORY_H
-#define _DUMPMEMORY_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* forward typedefs ***********************************************************/
-
-typedef struct dumpblock_t dumpblock_t;
-typedef struct dumpinfo_t  dumpinfo_t;
-
-#include "config.h"
-
-#include <stdint.h>
-#include <string.h>
-
-
-/* ATTENTION: We need to define dumpblock_t and dumpinfo_t before
-   internal includes, as we need dumpinfo_t as nested structure in
-   threadobject. */
-
-/* dumpblock ******************************************************************/
-
-#define DUMPBLOCKSIZE    2 << 13    /* 2 * 8192 bytes */
-#define ALIGNSIZE        8
-
-struct dumpblock_t {
-       dumpblock_t *prev;
-       void        *dumpmem;
-       int32_t      size;
-};
-
-
-/* dump_allocation *************************************************************
-
-   This struct is used to record dump memory allocations for ENABLE_MEMCHECK.
-
-*******************************************************************************/
-
-#if defined(ENABLE_MEMCHECK)
-typedef struct dump_allocation_t dump_allocation_t;
-
-struct dump_allocation_t {
-       dump_allocation_t *next;
-       void              *mem;
-       int32_t            used;
-       int32_t            size;
-};
-#endif
-
-
-/* dumpinfo *******************************************************************/
-
-struct dumpinfo_t {
-       dumpblock_t       *block;                   /* the current top-most block */
-       int32_t            allocated;             /* allocated bytes in this area */
-       int32_t            used;                  /* used bytes in this dump area */
-#if defined(ENABLE_MEMCHECK)
-       dump_allocation_t *allocations;       /* list of allocations in this area */
-#endif
-};
-
-
-/* convenience macros *********************************************************/
-
-#define DMARKER               dumpmarker = dumpmemory_marker()
-#define DRELEASE              dumpmemory_release(dumpmarker)
-
-#define DNEW(type)            ((type *) dumpmemory_get(sizeof(type)))
-#define DMNEW(type,num)       ((type *) dumpmemory_get(sizeof(type) * (num)))
-#define DMREALLOC(ptr,type,num1,num2) ((type*) dumpmemory_realloc((ptr), sizeof(type) * (num1), \
-                                                                                                                                 sizeof(type) * (num2)))
-
-/* function prototypes ********************************************************/
-
-void    *dumpmemory_get(size_t size);
-void    *dumpmemory_realloc(void *src, int32_t len1, int32_t len2);
-int32_t  dumpmemory_marker(void);
-void     dumpmemory_release(int32_t size);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _DUMPMEMORY_H */
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
diff --git a/src/mm/dumpmemory.hpp b/src/mm/dumpmemory.hpp
new file mode 100644 (file)
index 0000000..c871d3e
--- /dev/null
@@ -0,0 +1,383 @@
+/* src/mm/dumpmemory.hpp - dump memory management
+
+   Copyright (C) 1996-2005, 2006, 2007, 2008
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+   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 _DUMPMEMORY_HPP
+#define _DUMPMEMORY_HPP
+
+#include "config.h"
+
+#include <assert.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+
+#include <cstddef>
+#include <list>
+#include <vector>
+#include <stdio.h> // REMOVEME
+
+
+// Forward declaration.
+class DumpMemoryArea;
+class DumpMemoryBlock;
+#if defined(ENABLE_MEMCHECK)
+class DumpMemoryAllocation;
+#endif
+
+
+/**
+ * Thread-local dump memory structure.
+ */
+class DumpMemory {
+private:
+       size_t                     _size;  ///< Size of the dump areas in this dump memory.
+       size_t                     _used;  ///< Used memory in this dump memory.
+       std::list<DumpMemoryArea*> _areas; ///< Pointer to the current dump area.
+
+public:
+       DumpMemory();
+       ~DumpMemory();
+
+       static inline DumpMemory* get_current();
+       static inline void*       allocate(size_t size);
+
+       inline void   add_size(size_t size) { _size += size; }
+
+       inline size_t get_size() const { return _size; }
+       inline size_t get_used() const { return _used; }
+
+       inline DumpMemoryArea* get_current_area() const;
+
+       static void* reallocate(void* src, size_t len1, size_t len2);
+
+       void  add_area(DumpMemoryArea* dma);
+       void  remove_area(DumpMemoryArea* dma);
+};
+
+
+/**
+ * Dump memory area.
+ */
+class DumpMemoryArea {
+private:
+       size_t                        _size;   ///< Size of the current memory block.
+       size_t                        _used;   ///< Used memory in the current memory block.
+       std::vector<DumpMemoryBlock*> _blocks; ///< List of memory blocks in this area.
+#if defined(ENABLE_MEMCHECK)
+       std::vector<DumpMemoryAllocation*> _allocs; ///< List of allocations in this area.
+#endif
+
+public:
+       DumpMemoryArea(size_t size = 0);
+       ~DumpMemoryArea();
+
+       inline size_t get_size() const { return _size; }
+       inline size_t get_used() const { return _used; }
+
+       // Inline functions.
+       inline void*            allocate(size_t size);
+       inline DumpMemoryBlock* get_current_block() const;
+
+       DumpMemoryBlock* allocate_new_block(size_t size);
+
+#if defined(ENABLE_MEMCHECK)
+private:
+       void check_canaries();
+#endif
+};
+
+
+/**
+ * Dump memory block.
+ */
+class DumpMemoryBlock {
+private:
+       static const size_t DEFAULT_SIZE = 2 << 13; // 2 * 8192 bytes
+
+       size_t _size;  ///< Size of the current memory block.
+       size_t _used;  ///< Used memory in the current memory block.
+       void*  _block; ///< List of memory blocks in this area.
+
+public:
+       DumpMemoryBlock(size_t size = 0);
+       ~DumpMemoryBlock();
+
+       inline size_t get_size() const { return _size; }
+       inline size_t get_used() const { return _used; }
+       inline size_t get_free() const { return _size - _used; }
+
+       // Inline functions.
+       inline void* allocate(size_t size);
+};
+
+
+/**
+ * Allocator for the dump memory.
+ */
+template<class T> class DumpMemoryAllocator {
+public:
+       // Type definitions.
+       typedef T              value_type;
+       typedef T*             pointer;
+       typedef const T*       const_pointer;
+       typedef T&             reference;
+       typedef const T&       const_reference;
+       typedef std::size_t    size_type;
+       typedef std::ptrdiff_t difference_type;
+
+       // Rebind allocator to type U.
+       template <class U> struct rebind {
+               typedef DumpMemoryAllocator<U> other;
+       };
+
+       // Constructors and destructor, nothing to do because the
+       // allocator has no state.
+       DumpMemoryAllocator() throw() {}
+       DumpMemoryAllocator(const DumpMemoryAllocator&) throw() {}
+       template <class U> DumpMemoryAllocator(const DumpMemoryAllocator<U>&) throw() {}
+
+       ~DumpMemoryAllocator() throw() {}
+
+       pointer allocate(size_type n, void* = 0) {
+//             printf("allocate: n=%d * %d\n", n, sizeof(T));
+               return static_cast<pointer>(DumpMemory::allocate(n * sizeof(T)));
+       }
+
+       // Initialize elements of allocated storage p with value value.
+       void construct(pointer p, const T& value) {
+//             printf("construct: p=%p, value=%p\n", (void*) p, (void*) value);
+               // Initialize memory with placement new.
+               new ((void*) p) T(value);
+       }
+
+       // Destroy elements of initialized storage p.
+       void destroy(pointer p) {
+//             printf("destroy: p=%p\n", (void*) p);
+               // Destroy objects by calling their destructor.
+               p->~T();
+       }
+
+       void deallocate(pointer p, size_type n) {
+//             printf("deallocate: p=%p, n=%d\n", (void*) p, n);
+               // We don't need to deallocate on dump memory.
+       }
+};
+
+
+/**
+ * Dump memory allocation, used for for ENABLE_MEMCHECK.
+ */
+#if defined(ENABLE_MEMCHECK)
+class DumpMemoryAllocation {
+private:
+       size_t _size;
+       void*  _mem;
+
+public:
+       DumpMemoryAllocation() : _size(0), _mem(NULL) {}
+       DumpMemoryAllocation(size_t size, void* mem) : _size(size), _mem(mem) {}
+       ~DumpMemoryAllocation() {};
+
+       inline size_t get_size() const { return _size; }
+       inline void*  get_mem()  const { return _mem; }
+};
+#endif
+
+
+// Includes.
+#include "mm/memory.h"
+
+#include "threads/thread.hpp"
+
+#include "vm/options.h"
+
+#if defined(ENABLE_STATISTICS)
+# include "vm/statistics.h"
+#endif
+
+
+// Inline functions.
+
+inline DumpMemory* DumpMemory::get_current()
+{
+       // Get the DumpMemory object of the current thread.
+       threadobject* t = thread_get_current();
+       DumpMemory* dm = t->_dumpmemory;
+       return dm;
+}
+
+inline DumpMemoryArea* DumpMemory::get_current_area() const
+{
+       return _areas.back();
+}
+
+inline void* DumpMemory::allocate(size_t size)
+{
+       DumpMemory* dm = get_current();
+       DumpMemoryArea* dma = dm->get_current_area();
+
+       size_t alignedsize = size;
+
+#if defined(ENABLE_MEMCHECK)
+       alignedsize += 2 * MEMORY_CANARY_SIZE;
+#endif
+
+       // Align the allocation size.
+       alignedsize = MEMORY_ALIGN(alignedsize, ALIGNSIZE);
+
+       void* p = dma->allocate(alignedsize);
+
+       // Increase the used count of the dump memory.
+       dm->_used += alignedsize;
+
+       return p;
+}
+
+inline DumpMemoryBlock* DumpMemoryArea::get_current_block() const
+{
+       return _blocks.empty() ? NULL : _blocks.back();
+}
+
+inline void* DumpMemoryArea::allocate(size_t size)
+{
+       DumpMemoryBlock* dmb = get_current_block();
+
+       // Check if we have a memory block or have enough memory in the
+       // current memory block.
+       if (dmb == NULL || size > dmb->get_free()) {
+               // No, allocate a new one.
+               dmb = allocate_new_block(size);
+
+               // Increase the size of the memory area.  We use get_size()
+               // here because the default size is very likely to be bigger
+               // than size.
+               _size += dmb->get_size();
+       }
+
+       void* p = dmb->allocate(size);
+
+#if defined(ENABLE_MEMCHECK)
+       uint8_t *pm;
+       size_t   origsize = size - 2 * MEMORY_CANARY_SIZE;
+
+       // Make p point after the bottom canary.
+
+       p = ((uint8_t *) p) + MEMORY_CANARY_SIZE;
+
+       // Add the allocation to our list of allocations
+
+       DumpMemoryAllocation* dma = new DumpMemoryAllocation(origsize, p);
+
+       _allocs.push_back(dma);
+
+       // Write the canaries.
+
+       pm = ((uint8_t *) p) - MEMORY_CANARY_SIZE;
+
+       for (int i = 0; i < MEMORY_CANARY_SIZE; ++i)
+               pm[i] = i + MEMORY_CANARY_FIRST_BYTE;
+
+       pm = ((uint8_t *) p) + dma->get_size();
+
+       for (int i = 0; i < MEMORY_CANARY_SIZE; ++i)
+               pm[i] = i + MEMORY_CANARY_FIRST_BYTE;
+
+       // Clear the memory.
+
+       (void) os::memset(p, MEMORY_CLEAR_BYTE, dma->get_size());
+#endif /* defined(ENABLE_MEMCHECK) */
+
+       // Increase the used size of the memory area.
+       _used += size;
+
+       return p;
+}
+
+/**
+ * Allocate memory in the current dump memory area.
+ *
+ * This function is a fast allocator suitable for scratch memory that
+ * can be collectively freed when the current activity (eg. compiling)
+ * is done.
+ *
+ * You cannot selectively free dump memory. Before you start
+ * allocating it, you remember the current size returned by
+ * `dumpmemory_marker`. Later, when you no longer need the memory,
+ * call `dumpmemory_release` with the remembered size and all dump
+ * memory allocated since the call to `dumpmemory_marker` will be
+ * freed.
+ *
+ * @parm size Size of block to allocate in bytes. May be zero, in which case NULL is returned
+ *
+ * @return Pointer to allocated memory, or NULL iff size was zero.
+ */
+void* DumpMemoryBlock::allocate(size_t size)
+{
+       if (size == 0)
+               return NULL;
+
+       // Sanity check.
+       assert(size <= (_size - _used));
+
+       // Calculate the memory address of the newly allocated memory.
+       void* p = (void*) (((uint8_t*) _block) + _used);
+
+       // Increase used memory block size by the allocated memory size.
+       _used += size;
+
+       return p;
+}
+
+#else
+
+// Legacy C interface.
+
+void* DumpMemory_allocate(size_t size);
+void* DumpMemory_reallocate(void* src, size_t len1, size_t len2);
+
+#define DNEW(type)                    ((type*) DumpMemory_allocate(sizeof(type)))
+#define DMNEW(type,num)               ((type*) DumpMemory_allocate(sizeof(type) * (num)))
+#define DMREALLOC(ptr,type,num1,num2) ((type*) DumpMemory_reallocate((ptr), sizeof(type) * (num1), sizeof(type) * (num2)))
+
+#endif
+
+#endif // _DUMPMEMORY_HPP
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
index 2b4f64a725ffd397623c37a2efda2927025ace6a..bfd612b010cf6be5879a74d721929707d003057f 100644 (file)
 
 #include "toolbox/logging.h"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/exceptions.hpp"
 #include "vm/finalizer.h"
 #include "vm/global.h"
-#include "vm/loader.h"
+#include "vm/loader.hpp"
 #include "vm/options.h"
 #include "vm/rt-timing.h"
 #include "vm/string.hpp"
@@ -240,7 +240,7 @@ void *gc_out_of_memory(size_t bytes_requested)
 
        if (in_gc_out_of_memory) {
                /* this is all we can do... */
-               vm_abort("gc_out_of_memory: out of memory");
+               os::abort("gc_out_of_memory: out of memory");
        }
 
        in_gc_out_of_memory = true;
@@ -265,7 +265,7 @@ void *gc_out_of_memory(size_t bytes_requested)
  * Emacs will automagically detect them.
  * ---------------------------------------------------------------------
  * Local variables:
- * mode: c
+ * mode: c++
  * indent-tabs-mode: t
  * c-basic-offset: 4
  * tab-width: 4
index 01209e0d619153b3edd1a9267d27796eda709d4e..d0a488d2ae205a9b300eb038df3b07cdda3e9dc7 100644 (file)
@@ -40,9 +40,9 @@
 
 #include "toolbox/logging.h"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/global.h"
-#include "vm/loader.h"
+#include "vm/loader.hpp"
 #include "vm/options.h"
 #include "vm/vm.hpp"
 
index 60d5c3ae58d75ac8d2577d9780abb34b2585a993..5e0d5e644c5f53b96e1c34d702273c122d94b92d 100644 (file)
 
 #include "config.h"
 
+#include <assert.h>
 #include <stdint.h>
 
+
 #ifdef __cplusplus
-extern "C" {
+
+class GC {
+public:
+};
+
+
+/**
+ * Critical section for the GC.
+ */
+class GCCriticalSection {
+public:
+       GCCriticalSection()  { enter(); }
+       ~GCCriticalSection() { leave(); }
+
+       inline static void enter ();
+       inline static void leave ();
+       inline static bool inside();
+};
+
+
+// Includes.
+#if defined(ENABLE_GC_CACAO)
+# include "threads/thread.hpp"
 #endif
 
-#include "vm/global.h"
-#include "vm/method.h"
+
+/**
+ * Enters a LLNI critical section which prevents the GC from moving
+ * objects around on the collected heap.
+ *
+ * There are no race conditions possible while entering such a critical
+ * section, because each thread only modifies its own thread local flag
+ * and the GC reads the flags while the world is stopped.
+ */
+void GCCriticalSection::enter()
+{
+#if defined(ENABLE_GC_CACAO)
+       threadobject* t = thread_get_current();
+
+       // Sanity check.
+       assert(t->gc_critical == false);
+
+       t->gc_critical = true;
+#endif
+}
+
+/**
+ * Leaves a LLNI critical section and allows the GC to move objects
+ * around on the collected heap again.
+ */
+void GCCriticalSection::leave()
+{
+#if defined(ENABLE_GC_CACAO)
+       threadobject* t = thread_get_current();
+
+       // Sanity check.
+       assert(t->gc_critical == true);
+
+       t->gc_critical = false;
+#endif
+}
+
+
+/**
+ * Checks if the calling thread is inside a GC critical section.
+ *
+ * @return true if inside, false otherwise.
+ */
+bool GCCriticalSection::inside()
+{
+#if defined(ENABLE_GC_CACAO)
+       threadobject* t = thread_get_current();
+       return t->gc_critical;
+#else
+       return true;
+#endif
+}
+
+#endif
 
 
 /* reference types ************************************************************/
@@ -52,8 +128,17 @@ enum {
 };
 
 
+// Includes.
+#include "vm/global.h"
+#include "vm/method.h"
+
+
 /* function prototypes ********************************************************/
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 void    gc_init(size_t heapmaxsize, size_t heapstartsize);
 
 void*   heap_alloc_uncollectable(size_t size);
@@ -83,7 +168,7 @@ void*   gc_out_of_memory(size_t bytes_requested);
 
 /* inlined functions **********************************************************/
 
-static inline int32_t heap_hashcode(java_object_t *obj)
+static inline int32_t heap_hashcode(java_object_tobj)
 {
 #if defined(ENABLE_GC_CACAO)
        return heap_get_hashcode(obj);
@@ -93,10 +178,10 @@ static inline int32_t heap_hashcode(java_object_t *obj)
 }
 
 #ifdef __cplusplus
-}
+} // extern "C"
 #endif
 
-#endif /* _GC_HPP */
+#endif // _GC_HPP
 
 
 /*
@@ -105,9 +190,10 @@ static inline int32_t heap_hashcode(java_object_t *obj)
  * Emacs will automagically detect them.
  * ---------------------------------------------------------------------
  * Local variables:
- * mode: c
+ * mode: c++
  * indent-tabs-mode: t
  * c-basic-offset: 4
  * tab-width: 4
  * End:
+ * vim:noexpandtab:sw=4:ts=4:
  */
index ccaa8ec4d1b196c579f1c888b3a5893c52d2abae..0774aee016228547abfe7b8d919478d22a72dc4a 100644 (file)
@@ -40,9 +40,9 @@
 
 #include "mm/memory.h"
 
-#include "native/native.h"
+#include "native/native.hpp"
 
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
 #include "threads/thread.hpp"
 
 #include "toolbox/logging.h"
index 12ca651c2eecd3f1b4ac872fab8ae2b73cc09d4c..ec6393f19f8a4ac959748a64750ca26a7cae8c89 100644 (file)
 
 #include "config.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <string.h>
+#include <stdint.h>
 
-#include "vm/types.h"
 
-#include "mm/codememory.h"
-#include "mm/dumpmemory.h"
+// Align the size of memory allocations to this size.
+#define ALIGNSIZE 8
+#define MEMORY_ALIGN(pos,size) ((((pos) + (size) - 1) / (size)) * (size))
 
 
-/* constants for ENABLE_MEMCHECK **********************************************/
+// Constants for ENABLE_MEMCHECK.
 
 #if defined(ENABLE_MEMCHECK)
 #define MEMORY_CANARY_SIZE          16
 #define MEMORY_CANARY_FIRST_BYTE    0xca
 #define MEMORY_CLEAR_BYTE           0xa5
-#endif /* defined(ENABLE_MEMCHECK) */
-
+#endif
 
-/* internal includes **********************************************************/
 
+// Includes.
+#include "mm/codememory.h"
+#include "mm/dumpmemory.hpp"
 #include "mm/gc.hpp"
 
 
@@ -91,7 +88,6 @@ Some more macros:
 
 */
 
-#define MEMORY_ALIGN(pos,size) ((((pos) + (size) - 1) / (size)) * (size))
 #define PADDING(pos,size)     (MEMORY_ALIGN((pos),(size)) - (pos))
 #define OFFSET(s,el)          ((int32_t) ((ptrint) &(((s*) 0)->el)))
 
@@ -130,6 +126,10 @@ Some more macros:
 
 /* function prototypes ********************************************************/
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 bool  memory_init(void);
 
 void  memory_mprotect(void *addr, size_t len, int prot);
index 48b40e307257225d88478007651bd12946923c47..6a6eab8afbeafd529563b21c58e5522a65f33c96 100644 (file)
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
+
 */
 
+
 #ifndef _MM_TLH_H
 #define _MM_TLH_H
 
+#include "config.h"
+
 #include <stddef.h>
 #include <stdint.h>
 
@@ -35,6 +39,10 @@ typedef struct {
        unsigned overflows;
 } tlh_t;
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 void tlh_init(tlh_t *tlh);
 
 void tlh_destroy(tlh_t *tlh);
@@ -45,6 +53,10 @@ void tlh_remove_frame(tlh_t *tlh);
 
 void *tlh_alloc(tlh_t *tlh, size_t size);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif
 
 /*
index facd048b9b37b4dcc6fc18a5fb690a929b8b8b59..4806f11499a351bbd8eb16c9634bdac073eb4bfa 100644 (file)
@@ -38,17 +38,17 @@ noinst_LTLIBRARIES = libnative.la
 if ENABLE_JNI
 JNI_SOURCES = \
        jni.cpp \
-       jni.h \
-       localref.c \
-       localref.h
+       jni.hpp \
+       localref.cpp \
+       localref.hpp
 endif
 
 libnative_la_SOURCES = \
        $(JNI_SOURCES) \
        llni.c \
        llni.h \
-       native.c \
-       native.h
+       native.cpp \
+       native.hpp
 
 libnative_la_LIBADD = \
        vm/libnativevm.la \
index 842840bdcc4122375a74fb77e2def6126a52b490..c88888fed4680812a67dae23e7244ad3feb07705 100644 (file)
 #include "mm/gc.hpp"
 #include "mm/memory.h"
 
-#include "native/jni.h"
+#include "native/jni.hpp"
 #include "native/llni.h"
-#include "native/localref.h"
-#include "native/native.h"
+#include "native/localref.hpp"
+#include "native/native.hpp"
 
 #if defined(ENABLE_JVMTI)
 # include "native/jvmti/cacaodbg.h"
 #endif
 
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
+#include "threads/mutex.hpp"
 #include "threads/thread.hpp"
 
 #include "toolbox/logging.h"
 
-#include "vm/array.h"
-#include "vm/builtin.h"
+#include "vm/array.hpp"
+#include "vm/jit/builtin.hpp"
 #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/loader.hpp"
 #include "vm/options.h"
 #include "vm/primitive.hpp"
 #include "vm/resolve.h"
@@ -63,9 +64,8 @@
 #include "vm/string.hpp"
 #include "vm/vm.hpp"
 
-#include "vm/jit/argument.h"
 #include "vm/jit/asmpart.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
 #include "vm/jit/stacktrace.hpp"
 
 
@@ -1448,24 +1448,21 @@ jboolean _Jv_JNI_IsInstanceOf(JNIEnv *env, jobject obj, jclass clazz)
 jmethodID jni_FromReflectedMethod(JNIEnv *env, jobject method)
 {
 #if defined(ENABLE_JAVASE)
-       java_handle_t* o;
        methodinfo*    m;
 
        TRACEJNICALLS(("jni_FromReflectedMethod(env=%p, method=%p)", env, method));
 
-       o = (java_handle_t *) method;
+       java_lang_Object o(method);
 
-       if (o == NULL)
+       if (o.is_null())
                return NULL;
 
-       // FIXME We can't access the object here directly.
-       if (o->vftbl->clazz == class_java_lang_reflect_Constructor) {
+       if (o.get_Class() == class_java_lang_reflect_Constructor) {
                java_lang_reflect_Constructor rc(method);
                m = rc.get_method();
        }
        else {
-               // FIXME We can't access the object here directly.
-               assert(o->vftbl->clazz == class_java_lang_reflect_Method);
+               assert(o.get_Class() == class_java_lang_reflect_Method);
 
                java_lang_reflect_Method rm(method);
                m = rm.get_method();
@@ -2975,20 +2972,18 @@ JNI_SET_ARRAY_REGION(Double,  jdouble,  double,  double)
 
 *******************************************************************************/
 
-jint _Jv_JNI_RegisterNatives(JNIEnv *env, jclass clazz,
-                                                        const JNINativeMethod *methods, jint nMethods)
+jint jni_RegisterNatives(JNIEnv* env, jclass clazz, const JNINativeMethod* methods, jint nMethods)
 {
-       classinfo *c;
+       TRACEJNICALLS(("jni_RegisterNatives(env=%p, clazz=%p, methods=%p, nMethods=%d)", env, clazz, methods, nMethods));
 
-       STATISTICS(jniinvokation());
-
-       c = LLNI_classinfo_unwrap(clazz);
+       classinfo* c = LLNI_classinfo_unwrap(clazz);
 
        /* XXX: if implemented this needs a call to jvmti_NativeMethodBind
        if (jvmti) jvmti_NativeMethodBind(method, address,  new_address_ptr);
        */
 
-       native_method_register(c->name, methods, nMethods);
+       NativeMethods& nm = VM::get_current()->get_nativemethods();
+       nm.register_methods(c->name, methods, nMethods);
 
     return 0;
 }
@@ -3081,7 +3076,7 @@ jint _Jv_JNI_GetJavaVM(JNIEnv *env, JavaVM **javavm)
 {
        STATISTICS(jniinvokation());
 
-    *javavm = vm->get_javavm();
+    *javavm = VM::get_current()->get_javavm();
 
        return 0;
 }
@@ -3244,7 +3239,7 @@ void _Jv_JNI_DeleteWeakGlobalRef(JNIEnv* env, jweak ref)
    argument.
 
 *******************************************************************************/
-    
+
 jobject jni_NewGlobalRef(JNIEnv* env, jobject obj)
 {
        hashtable_global_ref_entry *gre;
@@ -3256,7 +3251,7 @@ jobject jni_NewGlobalRef(JNIEnv* env, jobject obj)
 
        o = (java_handle_t *) obj;
 
-       LOCK_MONITOR_ENTER(hashtable_global_ref->header);
+       hashtable_global_ref->mutex->lock();
 
        LLNI_CRITICAL_START;
 
@@ -3311,7 +3306,7 @@ jobject jni_NewGlobalRef(JNIEnv* env, jobject obj)
                hashtable_global_ref->entries++;
        }
 
-       LOCK_MONITOR_EXIT(hashtable_global_ref->header);
+       hashtable_global_ref->mutex->unlock();
 
 #if defined(ENABLE_HANDLES)
        return gre;
@@ -3339,7 +3334,7 @@ void jni_DeleteGlobalRef(JNIEnv* env, jobject globalRef)
 
        o = (java_handle_t *) globalRef;
 
-       LOCK_MONITOR_ENTER(hashtable_global_ref->header);
+       hashtable_global_ref->mutex->lock();
 
        LLNI_CRITICAL_START;
 
@@ -3382,7 +3377,7 @@ void jni_DeleteGlobalRef(JNIEnv* env, jobject globalRef)
 
                        LLNI_CRITICAL_END;
 
-                       LOCK_MONITOR_EXIT(hashtable_global_ref->header);
+                       hashtable_global_ref->mutex->unlock();
 
                        return;
                }
@@ -3395,7 +3390,7 @@ void jni_DeleteGlobalRef(JNIEnv* env, jobject globalRef)
 
        LLNI_CRITICAL_END;
 
-       LOCK_MONITOR_EXIT(hashtable_global_ref->header);
+       hashtable_global_ref->mutex->unlock();
 }
 
 
@@ -3621,7 +3616,7 @@ jint _Jv_JNI_DestroyJavaVM(JavaVM *javavm)
 
        TRACEJNICALLS(("_Jv_JNI_DestroyJavaVM(javavm=%p)", javavm));
 
-       if (vm->is_created() == false)
+       if (VM::get_current()->is_created() == false)
                return JNI_ERR;
 
     status = vm_destroy(javavm);
@@ -3656,7 +3651,7 @@ static int jni_attach_current_thread(void **p_env, void *thr_args, bool isdaemon
        result = thread_current_is_attached();
 
        if (result == true) {
-               *p_env = vm->get_jnienv();
+               *p_env = VM::get_current()->get_jnienv();
                return JNI_OK;
        }
 
@@ -3675,7 +3670,7 @@ static int jni_attach_current_thread(void **p_env, void *thr_args, bool isdaemon
                return JNI_ERR;
 #endif
 
-       *p_env = vm->get_jnienv();
+       *p_env = VM::get_current()->get_jnienv();
 
        return JNI_OK;
 }
@@ -3687,7 +3682,7 @@ jint jni_AttachCurrentThread(JavaVM *javavm, void **p_env, void *thr_args)
 
        TRACEJNICALLS(("jni_AttachCurrentThread(javavm=%p, p_env=%p, thr_args=%p)", javavm, p_env, thr_args));
 
-       if (vm->is_created() == false)
+       if (VM::get_current()->is_created() == false)
                return JNI_ERR;
 
        result = jni_attach_current_thread(p_env, thr_args, false);
@@ -3756,7 +3751,7 @@ jint jni_GetEnv(JavaVM *javavm, void **env, jint version)
 {
        TRACEJNICALLS(("jni_GetEnv(javavm=%p, env=%p, version=%d)", javavm, env, version));
 
-       if (vm->is_created() == false) {
+       if (VM::get_current()->is_created() == false) {
                *env = NULL;
                return JNI_EDETACHED;
        }
@@ -3772,7 +3767,7 @@ jint jni_GetEnv(JavaVM *javavm, void **env, jint version)
        /* Check the JNI version. */
 
        if (jni_version_check(version) == true) {
-               *env = vm->get_jnienv();
+               *env = VM::get_current()->get_jnienv();
                return JNI_OK;
        }
 
@@ -3812,7 +3807,7 @@ jint jni_AttachCurrentThreadAsDaemon(JavaVM *javavm, void **penv, void *args)
 
        TRACEJNICALLS(("jni_AttachCurrentThreadAsDaemon(javavm=%p, penv=%p, args=%p)", javavm, penv, args));
 
-       if (vm->is_created() == false)
+       if (VM::get_current()->is_created() == false)
                return JNI_ERR;
 
        result = jni_attach_current_thread(penv, args, true);
@@ -4077,7 +4072,7 @@ struct JNINativeInterface_ _Jv_JNINativeInterface = {
        _Jv_JNI_SetFloatArrayRegion,
        _Jv_JNI_SetDoubleArrayRegion,
 
-       _Jv_JNI_RegisterNatives,
+       jni_RegisterNatives,
        _Jv_JNI_UnregisterNatives,
 
        _Jv_JNI_MonitorEnter,
@@ -4167,7 +4162,7 @@ jint JNI_GetCreatedJavaVMs(JavaVM **vmBuf, jsize bufLen, jsize *nVMs)
 
        // We currently only support 1 VM running.
 
-       vmBuf[0] = vm->get_javavm();
+       vmBuf[0] = VM::get_current()->get_javavm();
        *nVMs    = 1;
 
     return JNI_OK;
diff --git a/src/native/jni.h b/src/native/jni.h
deleted file mode 100644 (file)
index aacd850..0000000
+++ /dev/null
@@ -1,152 +0,0 @@
-/* src/native/jni.h - JNI types and data structures
-
-   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.
-
-*/
-
-
-/* jni.h ***********************************************************************
-
-   ATTENTION: We include this file before we actually define our own
-   jni.h.  We do this because otherwise we can get into unresolvable
-   circular header dependencies.
-
-   This is OK as GNU Classpath defines:
-
-   #define __CLASSPATH_JNI_MD_H__
-   #define _CLASSPATH_JNI_H
-
-   and OpenJDK defines:
-
-   #define _JAVASOFT_JNI_MD_H_
-   #define _JAVASOFT_JNI_H_
-
-   CLASSPATH_JNI_MD_H and CLASSPATH_JNI_H are defined in config.h.
-
-*******************************************************************************/
-
-#include "config.h"
-
-/* We include both headers with the absolute path so we can be sure
-   that the preprocessor does not take another header.  Furthermore we
-   include jni_md.h before jni.h as the latter includes the former. */
-
-#include INCLUDE_JNI_MD_H
-#include INCLUDE_JNI_H
-
-#ifndef _JNI_H
-#define _JNI_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "vm/types.h"
-
-#include "vm/global.h"
-#include "vm/method.h"
-
-
-#if 0
-/* _Jv_JNIEnv *****************************************************************/
-
-#ifndef __cplusplus
-
-// FIXME The __cplusplus define is just a quick workaround and needs
-// to be fixed properly.
-
-typedef struct _Jv_JNIEnv _Jv_JNIEnv;
-
-struct _Jv_JNIEnv {
-       const struct JNINativeInterface_ *env;    /* This MUST be the first entry */
-};
-
-#endif
-
-
-/* _Jv_JavaVM *****************************************************************/
-
-#ifndef __cplusplus
-
-// FIXME The __cplusplus define is just a quick workaround and needs
-// to be fixed properly.
-
-typedef struct _Jv_JavaVM _Jv_JavaVM;
-
-struct _Jv_JavaVM {
-       const struct JNIInvokeInterface_ *functions;/*This MUST be the first entry*/
-
-       /* JVM instance-specific variables */
-
-       s8 starttime;                       /* VM startup time                    */
-
-       s4 Java_gnu_java_lang_management_VMClassLoadingMXBeanImpl_verbose;
-       s4 Java_gnu_java_lang_management_VMMemoryMXBeanImpl_verbose;
-       s4 java_lang_management_ThreadMXBean_PeakThreadCount;
-       s4 java_lang_management_ThreadMXBean_ThreadCount;
-       s8 java_lang_management_ThreadMXBean_TotalStartedThreadCount;
-};
-
-#endif
-#endif
-
-
-/* CACAO related stuff ********************************************************/
-
-extern const struct JNIInvokeInterface_ _Jv_JNIInvokeInterface;
-extern struct JNINativeInterface_ _Jv_JNINativeInterface;
-
-
-/* hashtable_global_ref_entry *************************************************/
-
-typedef struct hashtable_global_ref_entry hashtable_global_ref_entry;
-
-struct hashtable_global_ref_entry {
-       java_object_t              *o;      /* object pointer of global ref       */
-       s4                          refs;   /* references of the current pointer  */
-       hashtable_global_ref_entry *hashlink; /* link for external chaining       */
-};
-
-
-/* function prototypes ********************************************************/
-
-bool jni_init(void);
-bool jni_version_check(int version);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _JNI_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:
- */
diff --git a/src/native/jni.hpp b/src/native/jni.hpp
new file mode 100644 (file)
index 0000000..16933ec
--- /dev/null
@@ -0,0 +1,202 @@
+/* src/native/jni.hpp - JNI types and data structures
+
+   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.
+
+*/
+
+
+/* jni.hpp *********************************************************************
+
+   ATTENTION: We include this file before we actually define our own
+   jni.h.  We do this because otherwise we can get into unresolvable
+   circular header dependencies.
+
+   GNU Classpath's headers define:
+
+   #define __CLASSPATH_JNI_MD_H__
+   #define _CLASSPATH_JNI_H
+
+   and jni.h uses:
+
+   _CLASSPATH_VM_JNI_TYPES_DEFINED
+   
+   OpenJDK's headers define:
+
+   #define _JAVASOFT_JNI_MD_H_
+   #define _JAVASOFT_JNI_H_
+
+   and jni.h uses:
+
+   JNI_TYPES_ALREADY_DEFINED_IN_JNI_MD_H
+
+   CLASSPATH_JNI_MD_H and CLASSPATH_JNI_H are defined in config.h.
+
+   We include both headers (jni.h and jni_md.h) with the absolute path
+   so we can be sure that the preprocessor does not pick up another
+   header from the search path.  Furthermore we include jni_md.h
+   before jni.h as the latter includes the former.
+
+*******************************************************************************/
+
+
+#ifndef _JNI_HPP
+#define _JNI_HPP
+
+#include "config.h"
+
+#include <stdbool.h>
+#include <stdint.h>
+
+
+// Define these to override the typedefs in jni.h
+#define _CLASSPATH_VM_JNI_TYPES_DEFINED          1 // GNU Classpath
+#define JNI_TYPES_ALREADY_DEFINED_IN_JNI_MD_H    1 // OpenJDK
+
+// First include jni_md.h so we have the Java primitive types.
+#include INCLUDE_JNI_MD_H
+
+
+// Include the C++ wrapper classes.
+//#include "vm/javaobjects.hpp"
+#include "vm/global.h"
+
+// Typedef the JNI types.
+typedef java_handle_t*              jobject;
+typedef java_handle_t*              jclass;
+typedef java_handle_t*              jstring;
+typedef java_handle_t*              jthrowable;
+typedef java_handle_t*              jweak; // FIXME
+typedef java_handle_array_t*        jarray;
+typedef java_handle_objectarray_t*  jobjectArray;
+typedef java_handle_booleanarray_t* jbooleanArray;
+typedef java_handle_bytearray_t*    jbyteArray;
+typedef java_handle_chararray_t*    jcharArray;
+typedef java_handle_shortarray_t*   jshortArray;
+typedef java_handle_intarray_t*     jintArray;
+typedef java_handle_longarray_t*    jlongArray;
+typedef java_handle_floatarray_t*   jfloatArray;
+typedef java_handle_doublearray_t*  jdoubleArray;
+
+
+// We need some additional stuff for the various JNI headers.
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH) || defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
+
+// These typedefs and defines are copied from GNU Classpath's jni.h
+#define JNI_TRUE true
+#define JNI_FALSE false
+
+typedef struct _Jv_JNIEnv JNIEnv;
+typedef struct _Jv_JavaVM JavaVM;
+
+#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+
+// These typedefs are copied from OpenJDK's jni.h
+typedef unsigned char   jboolean;
+typedef unsigned short  jchar;
+typedef short           jshort;
+typedef float           jfloat;
+typedef double          jdouble;
+
+typedef jint            jsize;
+
+typedef union jvalue {
+    jboolean z;
+    jbyte    b;
+    jchar    c;
+    jshort   s;
+    jint     i;
+    jlong    j;
+    jfloat   f;
+    jdouble  d;
+    jobject  l;
+} jvalue;
+
+struct _jfieldID;
+typedef struct _jfieldID *jfieldID;
+
+struct _jmethodID;
+typedef struct _jmethodID *jmethodID;
+
+/* Return values from jobjectRefType */
+typedef enum _jobjectType {
+     JNIInvalidRefType    = 0,
+     JNILocalRefType      = 1,
+     JNIGlobalRefType     = 2,
+     JNIWeakGlobalRefType = 3
+} jobjectRefType;
+
+#endif
+
+
+// Now include jni.h to complete the JNI header.
+#include INCLUDE_JNI_H
+
+
+// Includes.
+#include "vm/global.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* CACAO related stuff ********************************************************/
+
+extern const struct JNIInvokeInterface_ _Jv_JNIInvokeInterface;
+extern struct JNINativeInterface_ _Jv_JNINativeInterface;
+
+
+/* hashtable_global_ref_entry *************************************************/
+
+typedef struct hashtable_global_ref_entry hashtable_global_ref_entry;
+
+struct hashtable_global_ref_entry {
+       java_object_t              *o;      /* object pointer of global ref       */
+       int32_t                     refs;   /* references of the current pointer  */
+       hashtable_global_ref_entry *hashlink; /* link for external chaining       */
+};
+
+
+/* function prototypes ********************************************************/
+
+bool jni_init(void);
+bool jni_version_check(int version);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _JNI_HPP
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
index ced10d58fa02060213e106d1e08615432943296e..eb29c6f7b5313c27252ea99087e8647816281fd3 100644 (file)
@@ -27,9 +27,9 @@
 #include "native/jvmti/cacaodbg.h"
 #include "native/jvmti/dbg.h"
 #include "vm/vm.hpp"
-#include "vm/loader.h"
+#include "vm/loader.hpp"
 #include "vm/exceptions.hpp"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/jit/asmpart.h"
 #include "vm/string.hpp"
 #include "toolbox/logging.h"
index 49e7f795c24be6a4e5819a26b70d4631fafeaa0a..42aa02492bb9e4e41e499c8ebca54f06838624f0 100644 (file)
 #include <unistd.h>
 #include <sched.h>
 
-#include "native/jni.h"
-#include "native/native.h"
+#include "native/jni.hpp"
+#include "native/native.hpp"
 #include "native/jvmti/cacaodbg.h"
 #include "native/jvmti/jvmti.h"
 #include "vm/jit/stacktrace.hpp"
 #include "vm/global.h"
-#include "vm/loader.h"
-#include "vm/builtin.h"
+#include "vm/loader.hpp"
+#include "vm/jit/builtin.hpp"
 #include "vm/jit/asmpart.h"
 #include "vm/class.h"
 #include "vm/classcache.h"
@@ -54,7 +54,7 @@
 #include "mm/memory.h"
 #include "threads/mutex.h"
 #include "threads/thread.hpp"
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
 #include "vm/exceptions.hpp"
 #include "native/include/java_io_PrintStream.h"
 #include "native/include/java_io_InputStream.h"
@@ -63,7 +63,7 @@
 #include "native/include/java_lang_VMObject.h"
 #include "native/include/java_lang_VMSystem.h"
 #include "native/include/java_lang_VMClass.h"
-#include "vm/suck.h"
+#include "vm/suck.hpp"
 #include "boehm-gc/include/gc.h"
 
 #if defined(ENABLE_THREADS)
index b0774abb289b260ef83c63b1c13dc91b49e2664b..576c7ee2b0643a315c75a8e10507e0d077025ca4 100644 (file)
@@ -1,10 +1,8 @@
 /* src/native/jvmti.c - implementation of the Java Virtual Machine Tool 
                         Interface functions
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
-   C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
-   E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
-   J. Wenninger, Institut f. Computersprachen - TU Wien
+   Copyright (C) 1996-2005, 2006, 2008
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
 
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Author: Martin Platter
-
-   Changes:             
+*/
 
-   
 
-*/
 #ifndef _JVMTI_H
 #define _JVMTI_H
 
-#include "native/jni.h"
+#include "config.h"
+
+#include "native/jni.hpp"
 
 
 #define JVMTI_VERSION_INTERFACE_JNI   0x00000000
index 043d82964baa26a3bcd6e12dc88b8e9857ab4735..6112dfbfe4a4b286db7632a7e3430ef3219c7e91 100644 (file)
 #ifndef _LLNI_H
 #define _LLNI_H
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #include "config.h"
 
 /* forward defines ************************************************************/
@@ -55,7 +51,7 @@ extern "C" {
 #endif
 
 
-#include "native/localref.h"
+#include "native/localref.hpp"
 
 #include "threads/thread.hpp"
 
@@ -149,6 +145,10 @@ extern "C" {
 # define LLNI_CRITICAL_END_THREAD(t)
 #endif
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 void llni_critical_start();
 void llni_critical_end();
 void llni_critical_start_thread(threadobject *t);
diff --git a/src/native/localref.c b/src/native/localref.c
deleted file mode 100644 (file)
index f686858..0000000
+++ /dev/null
@@ -1,642 +0,0 @@
-/* src/native/localref.c - Management of local reference tables
-
-   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 "mm/memory.h"
-
-#include "native/localref.h"
-
-#include "threads/thread.hpp"
-
-#include "toolbox/logging.h"
-
-#include "vm/options.h"
-#include "vm/vm.hpp"
-
-#include "vm/jit/argument.h"
-
-
-/* debug **********************************************************************/
-
-#if !defined(NDEBUG)
-# define DEBUGLOCALREF(message, index) \
-       do { \
-               if (opt_DebugLocalReferences) { \
-                       localref_table *dlrt = LOCALREFTABLE; \
-                       log_start(); \
-                       log_print("[local reference %-12s: lrt=%016p frame=%d capacity=%d used=%d", message, dlrt, dlrt->localframes, dlrt->capacity, dlrt->used); \
-                       if (index >= 0) \
-                               log_print(" localref=%p object=%p", &(dlrt->refs[index]), dlrt->refs[index]); \
-                       log_print("]"); \
-                       log_finish(); \
-               } \
-       } while (0)
-#else
-# define DEBUGLOCALREF(message, index)
-#endif
-
-
-/* global variables ***********************************************************/
-
-#if !defined(ENABLE_THREADS)
-localref_table *_no_threads_localref_table;
-#endif
-
-
-/* some forward declarations **************************************************/
-
-#if !defined(NDEBUG)
-static bool localref_check_uncleared();
-#endif
-
-
-/* localref_table_init *********************************************************
-
-   Initializes the local references table of the current thread.
-
-*******************************************************************************/
-
-bool localref_table_init(void)
-{
-       localref_table *lrt;
-
-       TRACESUBSYSTEMINITIALIZATION("localref_table_init");
-
-       assert(LOCALREFTABLE == NULL);
-
-#if !defined(ENABLE_GC_BOEHM)
-       /* this is freed by localref_table_destroy */
-       lrt = NEW(localref_table);
-#else
-       /* this does not need to be freed again */
-       lrt = GCNEW(localref_table);
-#endif
-
-       if (lrt == NULL)
-               return false;
-
-       localref_table_add(lrt);
-
-       DEBUGLOCALREF("table init", -1);
-
-       return true;
-}
-
-
-/* localref_table_destroy ******************************************************
-
-   Destroys the complete local references table of the current thread.
-
-*******************************************************************************/
-
-bool localref_table_destroy(void)
-{
-       localref_table *lrt;
-
-       lrt = LOCALREFTABLE;
-       assert(lrt != NULL);
-       assert(lrt->prev == NULL);
-
-       DEBUGLOCALREF("table destroy", -1);
-
-#if !defined(ENABLE_GC_BOEHM)
-       FREE(lrt, localref_table);
-#endif
-
-       LOCALREFTABLE = NULL;
-
-       return true;
-}
-
-
-/* localref_table_add **********************************************************
-
-   Adds a new local references table to the current thread.
-
-*******************************************************************************/
-
-void localref_table_add(localref_table *lrt)
-{
-       /* initialize the local reference table */
-
-       lrt->capacity    = LOCALREFTABLE_CAPACITY;
-       lrt->used        = 0;
-       lrt->localframes = 1;
-       lrt->prev        = LOCALREFTABLE;
-
-       /* clear the references array (memset is faster the a for-loop) */
-
-       MSET(lrt->refs, 0, void*, LOCALREFTABLE_CAPACITY);
-
-       /* add given local references table to this thread */
-
-       LOCALREFTABLE = lrt;
-
-       /*DEBUGLOCALREF("table add", -1);*/
-}
-
-
-/* localref_table_remove *******************************************************
-
-   Removes the topmost local references table from the current thread.
-
-*******************************************************************************/
-
-void localref_table_remove()
-{
-       localref_table *lrt;
-
-#if !defined(NDEBUG)
-       /* check for uncleared local references */
-
-       localref_check_uncleared();
-#endif
-
-       /* get current local reference table from thread */
-
-       lrt = LOCALREFTABLE;
-       assert(lrt != NULL);
-       assert(lrt->localframes == 1);
-
-       /*DEBUGLOCALREF("table remove", -1);*/
-
-       lrt = lrt->prev;
-
-       LOCALREFTABLE = lrt;
-}
-
-
-/* localref_frame_push *********************************************************
-
-   Creates a new local reference frame, in which at least a given
-   number of local references can be created.
-
-*******************************************************************************/
-
-bool localref_frame_push(int32_t capacity)
-{
-       localref_table *lrt;
-       localref_table *nlrt;
-       int32_t         additionalrefs;
-
-       /* get current local reference table from thread */
-
-       lrt = LOCALREFTABLE;
-       assert(lrt != NULL);
-       assert(capacity > 0);
-
-       /* Allocate new local reference table on Java heap.  Calculate the
-          additional memory we have to allocate. */
-
-       if (capacity > LOCALREFTABLE_CAPACITY)
-               additionalrefs = capacity - LOCALREFTABLE_CAPACITY;
-       else
-               additionalrefs = 0;
-
-#if !defined(ENABLE_GC_BOEHM)
-       nlrt = (localref_table *)
-                       MNEW(u1, sizeof(localref_table) + additionalrefs * SIZEOF_VOID_P);
-#else
-       nlrt = (localref_table *)
-                       GCMNEW(u1, sizeof(localref_table) + additionalrefs * SIZEOF_VOID_P);
-#endif
-
-       if (nlrt == NULL)
-               return false;
-
-       /* Set up the new local reference table and add it to the local
-          frames chain. */
-
-       nlrt->capacity    = capacity;
-       nlrt->used        = 0;
-       nlrt->localframes = lrt->localframes + 1;
-       nlrt->prev        = lrt;
-
-       /* store new local reference table in thread */
-
-       LOCALREFTABLE = nlrt;
-
-       DEBUGLOCALREF("frame push", -1);
-
-       return true;
-}
-
-
-/* localref_frame_pop_all ******************************************************
-
-   Pops off all the local reference frames of the current table.
-
-*******************************************************************************/
-
-void localref_frame_pop_all(void)
-{
-       localref_table *lrt;
-       localref_table *plrt;
-       int32_t         localframes;
-#if !defined(ENABLE_GC_BOEHM)
-       int32_t         additionalrefs;
-#endif
-
-       /* get current local reference table from thread */
-
-       lrt = LOCALREFTABLE;
-       assert(lrt != NULL);
-
-       localframes = lrt->localframes;
-
-       /* Don't delete the top local frame, as this one is allocated in
-          the native stub on the stack and is freed automagically on
-          return. */
-
-       if (localframes == 1)
-               return;
-
-       /* release all current local frames */
-
-       for (; localframes > 1; localframes--) {
-               /* get previous frame */
-
-               plrt = lrt->prev;
-
-               DEBUGLOCALREF("frame pop", -1);
-
-               /* clear all reference entries */
-
-               MSET(lrt->refs, 0, void*, lrt->capacity);
-
-               lrt->prev = NULL;
-
-#if !defined(ENABLE_GC_BOEHM)
-               /* for the exact GC local reference tables are not on the heap,
-                  so we need to free them explicitly here. */
-
-               if (lrt->capacity > LOCALREFTABLE_CAPACITY)
-                       additionalrefs = lrt->capacity - LOCALREFTABLE_CAPACITY;
-               else
-                       additionalrefs = 0;
-
-               MFREE(lrt, u1, sizeof(localref_table) + additionalrefs * SIZEOF_VOID_P);
-#endif
-
-               /* set new local references table */
-
-               lrt = plrt;
-       }
-
-       /* store new local reference table in thread */
-
-       LOCALREFTABLE = lrt;
-}
-
-
-/* localref_add ****************************************************************
-
-   Adds a new entry into the local reference table and returns the
-   new local reference.
-
-*******************************************************************************/
-
-java_handle_t *localref_add(java_object_t *o)
-{
-       localref_table *lrt;
-       java_handle_t  *h;
-       int32_t         i;
-
-       /* get current local reference table from thread */
-
-       lrt = LOCALREFTABLE;
-       assert(lrt != NULL);
-       assert(o != NULL);
-       /* XXX: assert that we are in a GC critical section! */
-
-       /* Check if we have space for the requested reference?  No,
-          allocate a new frame.  This is actually not what the spec says,
-          but for compatibility reasons... */
-
-    if (lrt->used == lrt->capacity) {
-               if (!localref_frame_push(64))
-                       assert(0);
-
-               /* get the new local reference table */ 
-
-               lrt = LOCALREFTABLE;
-       }
-
-       /* insert the reference into the local reference table */
-
-       for (i = 0; i < lrt->capacity; i++) {
-               if (lrt->refs[i] == NULL) {
-                       lrt->refs[i] = o;
-                       lrt->used++;
-
-#if defined(ENABLE_HANDLES)
-                       h = (java_handle_t *) &(lrt->refs[i]);
-#else
-                       h = (java_handle_t *) o;
-#endif
-
-                       /*DEBUGLOCALREF("entry add", i);*/
-
-                       return h;
-               }
-       }
-
-       /* this should not happen */
-
-       log_println("localref_add: WARNING: unable to add localref for %p", o);
-
-       return NULL;
-}
-
-
-/* localref_del ****************************************************************
-
-   Deletes an entry from the local reference table.
-
-*******************************************************************************/
-
-void localref_del(java_handle_t *localref)
-{
-       localref_table *lrt;
-       java_handle_t  *h;
-       int32_t         localframes;
-       int32_t         i;
-
-       /* get local reference table from thread */
-
-       lrt = LOCALREFTABLE;
-       assert(lrt != NULL);
-       assert(localref != NULL);
-
-       localframes = lrt->localframes;
-
-       /* go through all local frames of the current table */
-       /* XXX: this is propably not what the spec wants! */
-
-       for (; localframes > 0; localframes--) {
-
-               /* and try to remove the reference */
-    
-               for (i = 0; i < lrt->capacity; i++) {
-#if defined(ENABLE_HANDLES)
-                       h = (java_handle_t *) &(lrt->refs[i]);
-#else
-                       h = (java_handle_t *) lrt->refs[i];
-#endif
-
-                       if (h == localref) {
-                               DEBUGLOCALREF("entry delete", i);
-
-                               lrt->refs[i] = NULL;
-                               lrt->used--;
-
-                               return;
-                       }
-               }
-
-               lrt = lrt->prev;
-       }
-
-       /* this should not happen */
-
-       log_println("localref_del: WARNING: unable to find localref %p", localref);
-}
-
-
-/* localref_native_enter *******************************************************
-
-   Insert arguments to a native method into the local reference table.
-   This is done by the native stub through codegen_start_native_call.
-
-*******************************************************************************/
-
-void localref_native_enter(methodinfo *m, uint64_t *argument_regs, uint64_t *argument_stack)
-{
-       localref_table *lrt;
-       methoddesc     *md;
-       imm_union       arg;
-       java_handle_t  *h;
-       int i;
-
-       /* get local reference table from thread */
-
-       lrt = LOCALREFTABLE;
-       assert(lrt != NULL);
-       assert(m != NULL);
-
-       md = m->parseddesc;
-
-       /* walk through all parameters to the method */
-
-       for (i = 0; i < md->paramcount; ++i) {
-               /* load TYPE_ADR parameters ... */
-
-               if (md->paramtypes[i].type == TYPE_ADR) {
-                       arg = argument_jitarray_load(md, i, argument_regs, argument_stack);
-
-                       if (arg.a == NULL)
-                               continue;
-
-                       /* ... and insert them into the table */
-
-                       h = localref_add((java_object_t *) arg.a);
-
-#if defined(ENABLE_HANDLES)
-                       /* update the modified parameter if necesarry */
-
-                       arg.a = (void *) h;
-                       argument_jitarray_store(md, i, argument_regs, argument_stack, arg);
-#endif
-               }
-       }
-}
-
-
-/* localref_native_exit ********************************************************
-
-   Undo the wrapping of the return value of a native method. This is
-   done by the native stub through codegen_finish_native_call.
-
-   NOTE: This function is only useful if handles are enabled.
-
-*******************************************************************************/
-
-#if defined(ENABLE_HANDLES)
-void localref_native_exit(methodinfo *m, uint64_t *return_regs)
-{
-       localref_table *lrt;
-       methoddesc     *md;
-       imm_union       ret;
-       java_handle_t  *h;
-
-       /* get local reference table from thread */
-
-       lrt = LOCALREFTABLE;
-       assert(lrt != NULL);
-       assert(m != NULL);
-
-       md = m->parseddesc;
-
-       /* load TYPE_ADR return values ... */
-
-       if (md->returntype.type == TYPE_ADR) {
-               ret = argument_jitreturn_load(md, return_regs);
-
-               if (ret.a == NULL)
-                       return;
-
-               h = (java_handle_t *) ret.a;
-
-               /* update the modified return valie */
-
-               ret.a = (void *) h->heap_object;
-               argument_jitreturn_store(md, return_regs, ret);
-
-#if !defined(NDEBUG) && 0
-               /* removing the entry from the local reference table is not really
-                  necesarry, but gives us warnings if the entry does not exist. */
-
-               localref_del(h);
-#endif
-       }
-}
-#endif /* defined(ENABLE_HANDLES) */
-
-
-/* localref_dump ***************************************************************
-
-   Dumps all local reference tables, including all frames.
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-# define LOCALREF_DUMP_REFS_PER_LINE 4
-void localref_dump()
-{
-       localref_table *lrt;
-       int i, j;
-
-       /* get current local reference table from thread */
-
-       lrt = LOCALREFTABLE;
-
-       log_println("--------- Local Reference Tables Dump ---------");
-
-       while (lrt != NULL) {
-               log_println("Frame #%d, Used=%d, Capacity=%d, Addr=%p:", lrt->localframes, lrt->used, lrt->capacity, (void *) lrt);
-
-                       if (lrt->used != 0) {
-
-                               log_start();
-
-                               j = 0;
-                               for (i = 0; i < lrt->capacity; i++) {
-                                       if (lrt->refs[i] != NULL) {
-                                               if (j != 0 && j % LOCALREF_DUMP_REFS_PER_LINE == 0) {
-                                                       log_finish();
-                                                       log_start();
-                                               }
-                                               j++;
-                                               log_print("\t0x%016lx ", (intptr_t) lrt->refs[i]);
-                                       }
-                               }
-
-                               log_finish();
-                       }
-
-               lrt = lrt->prev;
-       }
-}
-#endif /* !defined(NDEBUG) */
-
-
-/* localref_check_uncleared ****************************************************
-
-   Checks the topmost local reference table for uncleared references.
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-static bool localref_check_uncleared()
-{
-       localref_table *lrt;
-       int32_t         localframes;
-       int32_t         lrt_uncleared;
-       int32_t         lrt_used;
-       int i;
-
-       /* get current local reference table from thread */
-
-       lrt = LOCALREFTABLE;
-       assert(lrt != NULL);
-       assert(lrt->localframes > 0);
-
-       localframes   = lrt->localframes;
-       lrt_uncleared = 0;
-       lrt_used      = 0;
-
-       for (; localframes > 0; localframes--) {
-               lrt_used += lrt->used;
-
-               for (i = 0; i < lrt->capacity; i++) {
-                       if (lrt->refs[i] != NULL)
-                               lrt_uncleared++;
-               }
-
-               lrt = lrt->prev;
-       }
-
-       if (lrt_uncleared != lrt_used) {
-               localref_dump();
-               vm_abort("localref_check_uncleared: (uncleared=%d) != (used=%d)", lrt_uncleared, lrt_used);
-       }
-
-       if (lrt_uncleared <= 1)
-               return true;
-       else {
-               /*log_println("localref_check_uncleared: %d uncleared local references", lrt_uncleared);*/
-               return false;
-       }
-}
-#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:
- */
diff --git a/src/native/localref.cpp b/src/native/localref.cpp
new file mode 100644 (file)
index 0000000..d236afb
--- /dev/null
@@ -0,0 +1,642 @@
+/* src/native/localref.cpp - Management of local reference tables
+
+   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 "mm/memory.h"
+
+#include "native/localref.hpp"
+
+#include "threads/thread.hpp"
+
+#include "toolbox/logging.h"
+
+#include "vm/options.h"
+#include "vm/vm.hpp"
+
+#include "vm/jit/argument.hpp"
+
+
+/* debug **********************************************************************/
+
+#if !defined(NDEBUG)
+# define DEBUGLOCALREF(message, index) \
+       do { \
+               if (opt_DebugLocalReferences) { \
+                       localref_table *dlrt = LOCALREFTABLE; \
+                       log_start(); \
+                       log_print("[local reference %-12s: lrt=%016p frame=%d capacity=%d used=%d", message, dlrt, dlrt->localframes, dlrt->capacity, dlrt->used); \
+                       if (index >= 0) \
+                               log_print(" localref=%p object=%p", &(dlrt->refs[index]), dlrt->refs[index]); \
+                       log_print("]"); \
+                       log_finish(); \
+               } \
+       } while (0)
+#else
+# define DEBUGLOCALREF(message, index)
+#endif
+
+
+/* global variables ***********************************************************/
+
+#if !defined(ENABLE_THREADS)
+localref_table *_no_threads_localref_table;
+#endif
+
+
+/* some forward declarations **************************************************/
+
+#if !defined(NDEBUG)
+static bool localref_check_uncleared();
+#endif
+
+
+/* localref_table_init *********************************************************
+
+   Initializes the local references table of the current thread.
+
+*******************************************************************************/
+
+bool localref_table_init(void)
+{
+       localref_table *lrt;
+
+       TRACESUBSYSTEMINITIALIZATION("localref_table_init");
+
+       assert(LOCALREFTABLE == NULL);
+
+#if !defined(ENABLE_GC_BOEHM)
+       /* this is freed by localref_table_destroy */
+       lrt = (localref_table*) NEW(localref_table);
+#else
+       /* this does not need to be freed again */
+       lrt = (localref_table*) GCNEW(localref_table);
+#endif
+
+       if (lrt == NULL)
+               return false;
+
+       localref_table_add(lrt);
+
+       DEBUGLOCALREF("table init", -1);
+
+       return true;
+}
+
+
+/* localref_table_destroy ******************************************************
+
+   Destroys the complete local references table of the current thread.
+
+*******************************************************************************/
+
+bool localref_table_destroy(void)
+{
+       localref_table *lrt;
+
+       lrt = LOCALREFTABLE;
+       assert(lrt != NULL);
+       assert(lrt->prev == NULL);
+
+       DEBUGLOCALREF("table destroy", -1);
+
+#if !defined(ENABLE_GC_BOEHM)
+       FREE(lrt, localref_table);
+#endif
+
+       LOCALREFTABLE = NULL;
+
+       return true;
+}
+
+
+/* localref_table_add **********************************************************
+
+   Adds a new local references table to the current thread.
+
+*******************************************************************************/
+
+void localref_table_add(localref_table *lrt)
+{
+       /* initialize the local reference table */
+
+       lrt->capacity    = LOCALREFTABLE_CAPACITY;
+       lrt->used        = 0;
+       lrt->localframes = 1;
+       lrt->prev        = LOCALREFTABLE;
+
+       /* clear the references array (memset is faster the a for-loop) */
+
+       MSET(lrt->refs, 0, void*, LOCALREFTABLE_CAPACITY);
+
+       /* add given local references table to this thread */
+
+       LOCALREFTABLE = lrt;
+
+       /*DEBUGLOCALREF("table add", -1);*/
+}
+
+
+/* localref_table_remove *******************************************************
+
+   Removes the topmost local references table from the current thread.
+
+*******************************************************************************/
+
+void localref_table_remove()
+{
+       localref_table *lrt;
+
+#if !defined(NDEBUG)
+       /* check for uncleared local references */
+
+       localref_check_uncleared();
+#endif
+
+       /* get current local reference table from thread */
+
+       lrt = LOCALREFTABLE;
+       assert(lrt != NULL);
+       assert(lrt->localframes == 1);
+
+       /*DEBUGLOCALREF("table remove", -1);*/
+
+       lrt = lrt->prev;
+
+       LOCALREFTABLE = lrt;
+}
+
+
+/* localref_frame_push *********************************************************
+
+   Creates a new local reference frame, in which at least a given
+   number of local references can be created.
+
+*******************************************************************************/
+
+bool localref_frame_push(int32_t capacity)
+{
+       localref_table *lrt;
+       localref_table *nlrt;
+       int32_t         additionalrefs;
+
+       /* get current local reference table from thread */
+
+       lrt = LOCALREFTABLE;
+       assert(lrt != NULL);
+       assert(capacity > 0);
+
+       /* Allocate new local reference table on Java heap.  Calculate the
+          additional memory we have to allocate. */
+
+       if (capacity > LOCALREFTABLE_CAPACITY)
+               additionalrefs = capacity - LOCALREFTABLE_CAPACITY;
+       else
+               additionalrefs = 0;
+
+#if !defined(ENABLE_GC_BOEHM)
+       nlrt = (localref_table *)
+                       MNEW(u1, sizeof(localref_table) + additionalrefs * SIZEOF_VOID_P);
+#else
+       nlrt = (localref_table *)
+                       GCMNEW(u1, sizeof(localref_table) + additionalrefs * SIZEOF_VOID_P);
+#endif
+
+       if (nlrt == NULL)
+               return false;
+
+       /* Set up the new local reference table and add it to the local
+          frames chain. */
+
+       nlrt->capacity    = capacity;
+       nlrt->used        = 0;
+       nlrt->localframes = lrt->localframes + 1;
+       nlrt->prev        = lrt;
+
+       /* store new local reference table in thread */
+
+       LOCALREFTABLE = nlrt;
+
+       DEBUGLOCALREF("frame push", -1);
+
+       return true;
+}
+
+
+/* localref_frame_pop_all ******************************************************
+
+   Pops off all the local reference frames of the current table.
+
+*******************************************************************************/
+
+void localref_frame_pop_all(void)
+{
+       localref_table *lrt;
+       localref_table *plrt;
+       int32_t         localframes;
+#if !defined(ENABLE_GC_BOEHM)
+       int32_t         additionalrefs;
+#endif
+
+       /* get current local reference table from thread */
+
+       lrt = LOCALREFTABLE;
+       assert(lrt != NULL);
+
+       localframes = lrt->localframes;
+
+       /* Don't delete the top local frame, as this one is allocated in
+          the native stub on the stack and is freed automagically on
+          return. */
+
+       if (localframes == 1)
+               return;
+
+       /* release all current local frames */
+
+       for (; localframes > 1; localframes--) {
+               /* get previous frame */
+
+               plrt = lrt->prev;
+
+               DEBUGLOCALREF("frame pop", -1);
+
+               /* clear all reference entries */
+
+               MSET(lrt->refs, 0, void*, lrt->capacity);
+
+               lrt->prev = NULL;
+
+#if !defined(ENABLE_GC_BOEHM)
+               /* for the exact GC local reference tables are not on the heap,
+                  so we need to free them explicitly here. */
+
+               if (lrt->capacity > LOCALREFTABLE_CAPACITY)
+                       additionalrefs = lrt->capacity - LOCALREFTABLE_CAPACITY;
+               else
+                       additionalrefs = 0;
+
+               MFREE(lrt, u1, sizeof(localref_table) + additionalrefs * SIZEOF_VOID_P);
+#endif
+
+               /* set new local references table */
+
+               lrt = plrt;
+       }
+
+       /* store new local reference table in thread */
+
+       LOCALREFTABLE = lrt;
+}
+
+
+/* localref_add ****************************************************************
+
+   Adds a new entry into the local reference table and returns the
+   new local reference.
+
+*******************************************************************************/
+
+java_handle_t *localref_add(java_object_t *o)
+{
+       localref_table *lrt;
+       java_handle_t  *h;
+       int32_t         i;
+
+       /* get current local reference table from thread */
+
+       lrt = LOCALREFTABLE;
+       assert(lrt != NULL);
+       assert(o != NULL);
+       /* XXX: assert that we are in a GC critical section! */
+
+       /* Check if we have space for the requested reference?  No,
+          allocate a new frame.  This is actually not what the spec says,
+          but for compatibility reasons... */
+
+    if (lrt->used == lrt->capacity) {
+               if (!localref_frame_push(64))
+                       assert(0);
+
+               /* get the new local reference table */ 
+
+               lrt = LOCALREFTABLE;
+       }
+
+       /* insert the reference into the local reference table */
+
+       for (i = 0; i < lrt->capacity; i++) {
+               if (lrt->refs[i] == NULL) {
+                       lrt->refs[i] = o;
+                       lrt->used++;
+
+#if defined(ENABLE_HANDLES)
+                       h = (java_handle_t *) &(lrt->refs[i]);
+#else
+                       h = (java_handle_t *) o;
+#endif
+
+                       /*DEBUGLOCALREF("entry add", i);*/
+
+                       return h;
+               }
+       }
+
+       /* this should not happen */
+
+       log_println("localref_add: WARNING: unable to add localref for %p", o);
+
+       return NULL;
+}
+
+
+/* localref_del ****************************************************************
+
+   Deletes an entry from the local reference table.
+
+*******************************************************************************/
+
+void localref_del(java_handle_t *localref)
+{
+       localref_table *lrt;
+       java_handle_t  *h;
+       int32_t         localframes;
+       int32_t         i;
+
+       /* get local reference table from thread */
+
+       lrt = LOCALREFTABLE;
+       assert(lrt != NULL);
+       assert(localref != NULL);
+
+       localframes = lrt->localframes;
+
+       /* go through all local frames of the current table */
+       /* XXX: this is propably not what the spec wants! */
+
+       for (; localframes > 0; localframes--) {
+
+               /* and try to remove the reference */
+    
+               for (i = 0; i < lrt->capacity; i++) {
+#if defined(ENABLE_HANDLES)
+                       h = (java_handle_t *) &(lrt->refs[i]);
+#else
+                       h = (java_handle_t *) lrt->refs[i];
+#endif
+
+                       if (h == localref) {
+                               DEBUGLOCALREF("entry delete", i);
+
+                               lrt->refs[i] = NULL;
+                               lrt->used--;
+
+                               return;
+                       }
+               }
+
+               lrt = lrt->prev;
+       }
+
+       /* this should not happen */
+
+       log_println("localref_del: WARNING: unable to find localref %p", localref);
+}
+
+
+/* localref_native_enter *******************************************************
+
+   Insert arguments to a native method into the local reference table.
+   This is done by the native stub through codegen_start_native_call.
+
+*******************************************************************************/
+
+void localref_native_enter(methodinfo *m, uint64_t *argument_regs, uint64_t *argument_stack)
+{
+       localref_table *lrt;
+       methoddesc     *md;
+       imm_union       arg;
+       java_handle_t  *h;
+       int i;
+
+       /* get local reference table from thread */
+
+       lrt = LOCALREFTABLE;
+       assert(lrt != NULL);
+       assert(m != NULL);
+
+       md = m->parseddesc;
+
+       /* walk through all parameters to the method */
+
+       for (i = 0; i < md->paramcount; ++i) {
+               /* load TYPE_ADR parameters ... */
+
+               if (md->paramtypes[i].type == TYPE_ADR) {
+                       arg = argument_jitarray_load(md, i, argument_regs, argument_stack);
+
+                       if (arg.a == NULL)
+                               continue;
+
+                       /* ... and insert them into the table */
+
+                       h = localref_add((java_object_t *) arg.a);
+
+#if defined(ENABLE_HANDLES)
+                       /* update the modified parameter if necesarry */
+
+                       arg.a = (void *) h;
+                       argument_jitarray_store(md, i, argument_regs, argument_stack, arg);
+#endif
+               }
+       }
+}
+
+
+/* localref_native_exit ********************************************************
+
+   Undo the wrapping of the return value of a native method. This is
+   done by the native stub through codegen_finish_native_call.
+
+   NOTE: This function is only useful if handles are enabled.
+
+*******************************************************************************/
+
+#if defined(ENABLE_HANDLES)
+void localref_native_exit(methodinfo *m, uint64_t *return_regs)
+{
+       localref_table *lrt;
+       methoddesc     *md;
+       imm_union       ret;
+       java_handle_t  *h;
+
+       /* get local reference table from thread */
+
+       lrt = LOCALREFTABLE;
+       assert(lrt != NULL);
+       assert(m != NULL);
+
+       md = m->parseddesc;
+
+       /* load TYPE_ADR return values ... */
+
+       if (md->returntype.type == TYPE_ADR) {
+               ret = argument_jitreturn_load(md, return_regs);
+
+               if (ret.a == NULL)
+                       return;
+
+               h = (java_handle_t *) ret.a;
+
+               /* update the modified return valie */
+
+               ret.a = (void *) h->heap_object;
+               argument_jitreturn_store(md, return_regs, ret);
+
+#if !defined(NDEBUG) && 0
+               /* removing the entry from the local reference table is not really
+                  necesarry, but gives us warnings if the entry does not exist. */
+
+               localref_del(h);
+#endif
+       }
+}
+#endif /* defined(ENABLE_HANDLES) */
+
+
+/* localref_dump ***************************************************************
+
+   Dumps all local reference tables, including all frames.
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+# define LOCALREF_DUMP_REFS_PER_LINE 4
+void localref_dump()
+{
+       localref_table *lrt;
+       int i, j;
+
+       /* get current local reference table from thread */
+
+       lrt = LOCALREFTABLE;
+
+       log_println("--------- Local Reference Tables Dump ---------");
+
+       while (lrt != NULL) {
+               log_println("Frame #%d, Used=%d, Capacity=%d, Addr=%p:", lrt->localframes, lrt->used, lrt->capacity, (void *) lrt);
+
+                       if (lrt->used != 0) {
+
+                               log_start();
+
+                               j = 0;
+                               for (i = 0; i < lrt->capacity; i++) {
+                                       if (lrt->refs[i] != NULL) {
+                                               if (j != 0 && j % LOCALREF_DUMP_REFS_PER_LINE == 0) {
+                                                       log_finish();
+                                                       log_start();
+                                               }
+                                               j++;
+                                               log_print("\t0x%016lx ", (intptr_t) lrt->refs[i]);
+                                       }
+                               }
+
+                               log_finish();
+                       }
+
+               lrt = lrt->prev;
+       }
+}
+#endif /* !defined(NDEBUG) */
+
+
+/* localref_check_uncleared ****************************************************
+
+   Checks the topmost local reference table for uncleared references.
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+static bool localref_check_uncleared()
+{
+       localref_table *lrt;
+       int32_t         localframes;
+       int32_t         lrt_uncleared;
+       int32_t         lrt_used;
+       int i;
+
+       /* get current local reference table from thread */
+
+       lrt = LOCALREFTABLE;
+       assert(lrt != NULL);
+       assert(lrt->localframes > 0);
+
+       localframes   = lrt->localframes;
+       lrt_uncleared = 0;
+       lrt_used      = 0;
+
+       for (; localframes > 0; localframes--) {
+               lrt_used += lrt->used;
+
+               for (i = 0; i < lrt->capacity; i++) {
+                       if (lrt->refs[i] != NULL)
+                               lrt_uncleared++;
+               }
+
+               lrt = lrt->prev;
+       }
+
+       if (lrt_uncleared != lrt_used) {
+               localref_dump();
+               vm_abort("localref_check_uncleared: (uncleared=%d) != (used=%d)", lrt_uncleared, lrt_used);
+       }
+
+       if (lrt_uncleared <= 1)
+               return true;
+       else {
+               /*log_println("localref_check_uncleared: %d uncleared local references", lrt_uncleared);*/
+               return false;
+       }
+}
+#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:
+ */
diff --git a/src/native/localref.h b/src/native/localref.h
deleted file mode 100644 (file)
index b1df773..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-/* src/native/localref.h - Management of local reference tables
-
-   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 _LOCALREF_H
-#define _LOCALREF_H
-
-/* forward typedefs ***********************************************************/
-
-typedef struct localref_table localref_table;
-
-#include "config.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "vm/types.h"
-
-#include "vm/global.h"
-#include "vm/method.h"
-
-
-/* localref_table **************************************************************
-
-   ATTENTION: keep this structure a multiple of 8-bytes!!! This is
-   essential for the native stub on 64-bit architectures.
-
-*******************************************************************************/
-
-#define LOCALREFTABLE_CAPACITY    16
-
-struct localref_table {
-       s4                 capacity;        /* table size                         */
-       s4                 used;            /* currently used references          */
-       s4                 localframes;     /* number of current frames           */
-       s4                 PADDING;         /* 8-byte padding                     */
-       localref_table    *prev;            /* link to prev table (LocalFrame)    */
-       java_object_t     *refs[LOCALREFTABLE_CAPACITY]; /* references            */
-};
-
-
-#if defined(ENABLE_THREADS)
-#define LOCALREFTABLE    (THREADOBJECT->_localref_table)
-#else
-extern localref_table *_no_threads_localref_table;
-
-#define LOCALREFTABLE    (_no_threads_localref_table)
-#endif
-
-
-/* function prototypes ********************************************************/
-
-bool localref_table_init(void);
-bool localref_table_destroy(void);
-void localref_table_add(localref_table *lrt);
-void localref_table_remove();
-
-bool localref_frame_push(int32_t capacity);
-void localref_frame_pop_all(void);
-
-java_handle_t *localref_add(java_object_t *o);
-void           localref_del(java_handle_t *localref);
-
-void localref_native_enter(methodinfo *m, uint64_t *argument_regs, uint64_t *argument_stack);
-void localref_native_exit(methodinfo *m, uint64_t *return_regs);
-
-#if !defined(NDEBUG)
-void localref_dump(void);
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _LOCALREF_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:
- */
diff --git a/src/native/localref.hpp b/src/native/localref.hpp
new file mode 100644 (file)
index 0000000..41142d9
--- /dev/null
@@ -0,0 +1,112 @@
+/* src/native/localref.hpp - Management of local reference tables
+
+   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 _LOCALREF_HPP
+#define _LOCALREF_HPP
+
+/* forward typedefs ***********************************************************/
+
+typedef struct localref_table localref_table;
+
+#include "config.h"
+
+#include "vm/types.h"
+
+#include "vm/global.h"
+#include "vm/method.h"
+
+
+/* localref_table **************************************************************
+
+   ATTENTION: keep this structure a multiple of 8-bytes!!! This is
+   essential for the native stub on 64-bit architectures.
+
+*******************************************************************************/
+
+#define LOCALREFTABLE_CAPACITY    16
+
+struct localref_table {
+       s4                 capacity;        /* table size                         */
+       s4                 used;            /* currently used references          */
+       s4                 localframes;     /* number of current frames           */
+       s4                 PADDING;         /* 8-byte padding                     */
+       localref_table    *prev;            /* link to prev table (LocalFrame)    */
+       java_object_t     *refs[LOCALREFTABLE_CAPACITY]; /* references            */
+};
+
+
+#if defined(ENABLE_THREADS)
+#define LOCALREFTABLE    (THREADOBJECT->_localref_table)
+#else
+extern localref_table *_no_threads_localref_table;
+
+#define LOCALREFTABLE    (_no_threads_localref_table)
+#endif
+
+
+/* function prototypes ********************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool localref_table_init(void);
+bool localref_table_destroy(void);
+void localref_table_add(localref_table *lrt);
+void localref_table_remove();
+
+bool localref_frame_push(int32_t capacity);
+void localref_frame_pop_all(void);
+
+java_handle_t *localref_add(java_object_t *o);
+void           localref_del(java_handle_t *localref);
+
+void localref_native_enter(methodinfo *m, uint64_t *argument_regs, uint64_t *argument_stack);
+void localref_native_exit(methodinfo *m, uint64_t *return_regs);
+
+#if !defined(NDEBUG)
+void localref_dump(void);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _LOCALREF_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:
+ */
diff --git a/src/native/native.c b/src/native/native.c
deleted file mode 100644 (file)
index f1aca47..0000000
+++ /dev/null
@@ -1,1019 +0,0 @@
-/* src/native/native.c - native library support
-
-   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 <ctype.h>
-
-#include <stdint.h>
-
-#include "vm/types.h"
-
-#include "mm/memory.h"
-
-#include "native/jni.h"
-#include "native/native.h"
-
-#include "native/vm/nativevm.h"
-
-#include "threads/lock-common.h"
-
-#include "toolbox/avl.h"
-#include "toolbox/hashtable.h"
-#include "toolbox/logging.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/os.hpp"
-#include "vm/resolve.h"
-#include "vm/string.hpp"
-#include "vm/vm.hpp"
-
-#include "vm/jit/asmpart.h"
-#include "vm/jit/jit.h"
-
-#if defined(ENABLE_JVMTI)
-#include "native/jvmti/cacaodbg.h"
-#endif
-
-
-/* global variables ***********************************************************/
-
-static avl_tree_t *tree_native_methods;
-
-#if defined(ENABLE_DL)
-static hashtable *hashtable_library;
-#endif
-
-
-/* prototypes *****************************************************************/
-
-static s4 native_tree_native_methods_comparator(const void *treenode, const void *node);
-
-
-/* native_init *****************************************************************
-
-   Initializes the native subsystem.
-
-*******************************************************************************/
-
-bool native_init(void)
-{
-       TRACESUBSYSTEMINITIALIZATION("native_init");
-
-#if defined(ENABLE_DL)
-       /* initialize library hashtable, 10 entries should be enough */
-
-       hashtable_library = NEW(hashtable);
-
-       hashtable_create(hashtable_library, 10);
-#endif
-
-       /* initialize the native methods table */
-
-       tree_native_methods = avl_create(&native_tree_native_methods_comparator);
-
-       /* everything's ok */
-
-       return true;
-}
-
-
-/* native_tree_native_methods_comparator ***************************************
-
-   Comparison function for AVL tree of native methods.
-
-   IN:
-       treenode....node in the tree
-          node........node to compare with tree-node
-
-   RETURN VALUE:
-       -1, 0, +1
-
-*******************************************************************************/
-
-static s4 native_tree_native_methods_comparator(const void *treenode, const void *node)
-{
-       const native_methods_node_t *treenmn;
-       const native_methods_node_t *nmn;
-
-       treenmn = treenode;
-       nmn     = node;
-
-       /* these are for walking the tree */
-
-       if (treenmn->classname < nmn->classname)
-               return -1;
-       else if (treenmn->classname > nmn->classname)
-               return 1;
-
-       if (treenmn->name < nmn->name)
-               return -1;
-       else if (treenmn->name > nmn->name)
-               return 1;
-
-       if (treenmn->descriptor < nmn->descriptor)
-               return -1;
-       else if (treenmn->descriptor > nmn->descriptor)
-               return 1;
-
-       /* all pointers are equal, we have found the entry */
-
-       return 0;
-}
-
-
-/* native_make_overloaded_function *********************************************
-
-   XXX
-
-*******************************************************************************/
-
-static utf *native_make_overloaded_function(utf *name, utf *descriptor)
-{
-       char *newname;
-       s4    namelen;
-       char *utf_ptr;
-       u2    c;
-       s4    i;
-       utf  *u;
-       int32_t dumpmarker;
-
-       /* mark memory */
-
-       DMARKER;
-
-       utf_ptr = descriptor->text;
-       namelen = strlen(name->text) + strlen("__") + strlen("0");
-
-       /* calculate additional length */
-
-       while ((c = utf_nextu2(&utf_ptr)) != ')') {
-               switch (c) {
-               case 'Z':
-               case 'B':
-               case 'C':
-               case 'S':
-               case 'I':
-               case 'J':
-               case 'F':
-               case 'D':
-                       namelen++;
-                       break;
-               case '[':
-                       namelen += 2;
-                       break;
-               case 'L':
-                       namelen++;
-                       while (utf_nextu2(&utf_ptr) != ';')
-                               namelen++;
-                       namelen += 2;
-                       break;
-               case '(':
-                       break;
-               default:
-                       assert(0);
-               }
-       }
-
-       /* reallocate memory */
-
-       i = strlen(name->text);
-
-       newname = DMNEW(char, namelen);
-       MCOPY(newname, name->text, char, i);
-
-       utf_ptr = descriptor->text;
-
-       newname[i++] = '_';
-       newname[i++] = '_';
-
-       while ((c = utf_nextu2(&utf_ptr)) != ')') {
-               switch (c) {
-               case 'Z':
-               case 'B':
-               case 'C':
-               case 'S':
-               case 'J':
-               case 'I':
-               case 'F':
-               case 'D':
-                       newname[i++] = c;
-                       break;
-               case '[':
-                       newname[i++] = '_';
-                       newname[i++] = '3';
-                       break;
-               case 'L':
-                       newname[i++] = 'L';
-                       while ((c = utf_nextu2(&utf_ptr)) != ';')
-                               if (((c >= 'a') && (c <= 'z')) ||
-                                       ((c >= 'A') && (c <= 'Z')) ||
-                                       ((c >= '0') && (c <= '9')))
-                                       newname[i++] = c;
-                               else
-                                       newname[i++] = '_';
-                       newname[i++] = '_';
-                       newname[i++] = '2';
-                       break;
-               case '(':
-                       break;
-               default:
-                       assert(0);
-               }
-       }
-
-       /* close string */
-
-       newname[i] = '\0';
-
-       /* make a utf-string */
-
-       u = utf_new_char(newname);
-
-       /* release memory */
-
-       DRELEASE;
-
-       return u;
-}
-
-
-/* native_insert_char **********************************************************
-
-   Inserts the passed UTF character into the native method name.  If
-   necessary it is escaped properly.
-
-*******************************************************************************/
-
-static s4 native_insert_char(char *name, u4 pos, u2 c)
-{
-       s4 val;
-       s4 i;
-
-       switch (c) {
-       case '/':
-       case '.':
-               /* replace '/' or '.' with '_' */
-               name[pos] = '_';
-               break;
-
-       case '_':
-               /* escape sequence for '_' is '_1' */
-               name[pos]   = '_';
-               name[++pos] = '1';
-               break;
-
-       case ';':
-               /* escape sequence for ';' is '_2' */
-               name[pos]   = '_';
-               name[++pos] = '2';
-               break;
-
-       case '[':
-               /* escape sequence for '[' is '_1' */
-               name[pos]   = '_';
-               name[++pos] = '3';
-               break;
-
-       default:
-               if (isalnum(c))
-                       name[pos] = c;
-               else {
-                       /* unicode character */
-                       name[pos]   = '_';
-                       name[++pos] = '0';
-
-                       for (i = 0; i < 4; ++i) {
-                               val = c & 0x0f;
-                               name[pos + 4 - i] = (val > 10) ? ('a' + val - 10) : ('0' + val);
-                               c >>= 4;
-                       }
-
-                       pos += 4;
-               }
-               break;
-       }
-
-       /* return the new buffer index */
-
-       return pos;
-}
-
-
-/* native_method_symbol ********************************************************
-
-   Generate a method-symbol string out of the class name and the
-   method name.
-
-*******************************************************************************/
-
-static utf *native_method_symbol(utf *classname, utf *methodname)
-{
-       char *name;
-       s4    namelen;
-       char *utf_ptr;
-       char *utf_endptr;
-       u2    c;
-       u4    pos;
-       utf  *u;
-       int32_t dumpmarker;
-
-       /* mark memory */
-
-       DMARKER;
-
-       /* Calculate length of native function name.  We multiply the
-          class and method name length by 6 as this is the maxium
-          escape-sequence that can be generated (unicode). */
-
-       namelen =
-               strlen("Java_") +
-               utf_get_number_of_u2s(classname) * 6 +
-               strlen("_") +
-               utf_get_number_of_u2s(methodname) * 6 +
-               strlen("0");
-
-       /* allocate memory */
-
-       name = DMNEW(char, namelen);
-
-       /* generate name of native functions */
-
-       strcpy(name, "Java_");
-       pos = strlen("Java_");
-
-       utf_ptr    = classname->text;
-       utf_endptr = UTF_END(classname);
-
-       for (; utf_ptr < utf_endptr; utf_ptr++, pos++) {
-               c   = *utf_ptr;
-               pos = native_insert_char(name, pos, c);
-       }
-
-       /* seperator between class and method */
-
-       name[pos++] = '_';
-
-       utf_ptr    = methodname->text;
-       utf_endptr = UTF_END(methodname);
-
-       for (; utf_ptr < utf_endptr; utf_ptr++, pos++) {
-               c   = *utf_ptr;
-               pos = native_insert_char(name, pos, c);
-       }
-
-       /* close string */
-
-       name[pos] = '\0';
-
-       /* check for an buffer overflow */
-
-       assert(pos <= namelen);
-
-       /* make a utf-string */
-
-       u = utf_new_char(name);
-
-       /* release memory */
-
-       DRELEASE;
-
-       return u;
-}
-
-
-/* native_method_register ******************************************************
-
-   Register a native method in the native method table.
-
-*******************************************************************************/
-
-void native_method_register(utf *classname, const JNINativeMethod *methods,
-                                                       int32_t count)
-{
-       native_methods_node_t *nmn;
-       utf                   *name;
-       utf                   *descriptor;
-       int32_t                i;
-
-       /* insert all methods passed */
-
-       for (i = 0; i < count; i++) {
-               if (opt_verbosejni) {
-                       printf("[Registering JNI native method ");
-                       utf_display_printable_ascii_classname(classname);
-                       printf(".%s]\n", methods[i].name);
-               }
-
-               /* generate the utf8 names */
-
-               name       = utf_new_char(methods[i].name);
-               descriptor = utf_new_char(methods[i].signature);
-
-               /* allocate a new tree node */
-
-               nmn = NEW(native_methods_node_t);
-
-               nmn->classname  = classname;
-               nmn->name       = name;
-               nmn->descriptor = descriptor;
-               nmn->function   = (functionptr) (ptrint) methods[i].fnPtr;
-
-               /* insert the method into the tree */
-
-               avl_insert(tree_native_methods, nmn);
-       }
-}
-
-
-/* native_method_find **********************************************************
-
-   Find a native method in the native method table.
-
-*******************************************************************************/
-
-static functionptr native_method_find(methodinfo *m)
-{
-       native_methods_node_t  tmpnmn;
-       native_methods_node_t *nmn;
-
-       /* fill the temporary structure used for searching the tree */
-
-       tmpnmn.classname  = m->clazz->name;
-       tmpnmn.name       = m->name;
-       tmpnmn.descriptor = m->descriptor;
-
-       /* find the entry in the AVL-tree */
-
-       nmn = avl_find(tree_native_methods, &tmpnmn);
-
-       if (nmn == NULL)
-               return NULL;
-
-       return nmn->function;
-}
-
-
-/* native_method_resolve *******************************************************
-
-   Resolves a native method, maybe from a dynamic library.
-
-   IN:
-       m ... methodinfo of the native Java method to resolve
-
-   RESULT:
-       pointer to the resolved method (symbol)
-
-*******************************************************************************/
-
-functionptr native_method_resolve(methodinfo *m)
-{
-       utf                            *name;
-       utf                            *newname;
-       functionptr                     f;
-#if defined(ENABLE_DL)
-       classloader_t                  *cl;
-       hashtable_library_loader_entry *le;
-       hashtable_library_name_entry   *ne;
-       u4                              key;    /* hashkey                        */
-       u4                              slot;   /* slot in hashtable              */
-#endif
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-       methodinfo                     *method_findNative;
-       java_handle_t                  *s;
-#endif
-
-       /* verbose output */
-
-       if (opt_verbosejni) {
-               printf("[Dynamic-linking native method ");
-               utf_display_printable_ascii_classname(m->clazz->name);
-               printf(".");
-               utf_display_printable_ascii(m->name);
-               printf(" ... ");
-       }
-
-       /* generate method symbol string */
-
-       name = native_method_symbol(m->clazz->name, m->name);
-
-       /* generate overloaded function (having the types in it's name)           */
-
-       newname = native_make_overloaded_function(name, m->descriptor);
-
-       /* check the library hash entries of the classloader of the
-          methods's class  */
-
-       f = NULL;
-
-#if defined(ENABLE_DL)
-       /* Get the classloader. */
-
-       cl = class_get_classloader(m->clazz);
-
-       /* normally addresses are aligned to 4, 8 or 16 bytes */
-
-       key  = ((u4) (ptrint) cl) >> 4;                       /* align to 16-byte */
-       slot = key & (hashtable_library->size - 1);
-       le   = hashtable_library->ptr[slot];
-
-       /* iterate through loaders in this hash slot */
-
-       while ((le != NULL) && (f == NULL)) {
-               /* iterate through names in this loader */
-
-               ne = le->namelink;
-                       
-               while ((ne != NULL) && (f == NULL)) {
-                       f = (functionptr) (ptrint) os_dlsym(ne->handle, name->text);
-
-                       if (f == NULL)
-                               f = (functionptr) (ptrint) os_dlsym(ne->handle, newname->text);
-
-                       ne = ne->hashlink;
-               }
-
-               le = le->hashlink;
-       }
-
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-       if (f == NULL) {
-               /* We can resolve the function directly from
-                  java.lang.ClassLoader as it's a static function. */
-               /* XXX should be done in native_init */
-
-               method_findNative =
-                       class_resolveclassmethod(class_java_lang_ClassLoader,
-                                                                        utf_findNative,
-                                                                        utf_java_lang_ClassLoader_java_lang_String__J,
-                                                                        class_java_lang_ClassLoader,
-                                                                        true);
-
-               if (method_findNative == NULL)
-                       return NULL;
-
-               /* try the normal name */
-
-               s = javastring_new(name);
-
-               f = (functionptr) (intptr_t) vm_call_method_long(method_findNative,
-                                                                                                                NULL, cl, s);
-
-               /* if not found, try the mangled name */
-
-               if (f == NULL) {
-                       s = javastring_new(newname);
-
-                       f = (functionptr) (intptr_t) vm_call_method_long(method_findNative,
-                                                                                                                        NULL, cl, s);
-               }
-       }
-# endif
-
-       if (f != NULL)
-               if (opt_verbosejni)
-                       printf("JNI ]\n");
-#endif
-
-       /* If not found, try to find the native function symbol in the
-          main program. */
-
-       if (f == NULL) {
-               f = native_method_find(m);
-
-               if (f != NULL)
-                       if (opt_verbosejni)
-                               printf("internal ]\n");
-       }
-
-#if defined(ENABLE_JVMTI)
-       /* fire Native Method Bind event */
-       if (jvmti) jvmti_NativeMethodBind(m, f, &f);
-#endif
-
-       /* no symbol found? throw exception */
-
-       if (f == NULL) {
-               if (opt_verbosejni)
-                       printf("failed ]\n");
-
-               exceptions_throw_unsatisfiedlinkerror(m->name);
-       }
-
-       return f;
-}
-
-
-/* native_library_open *********************************************************
-
-   Open a native library with the given utf8 name.
-
-   IN:
-       filename ... filename of the library to open
-
-   RETURN:
-       handle of the opened library
-
-*******************************************************************************/
-
-#if defined(ENABLE_DL)
-void* native_library_open(utf *filename)
-{
-       void* handle;
-
-       if (opt_verbosejni) {
-               printf("[Loading native library ");
-               utf_display_printable_ascii(filename);
-               printf(" ... ");
-       }
-
-       /* try to open the library */
-
-       handle = os_dlopen(filename->text, RTLD_LAZY);
-
-       if (handle == NULL) {
-               if (opt_verbosejni)
-                       printf("failed ]\n");
-
-               if (opt_verbose) {
-                       log_start();
-                       log_print("native_library_open: os_dlopen failed: ");
-                       log_print(dlerror());
-                       log_finish();
-               }
-
-               return NULL;
-       }
-
-       if (opt_verbosejni)
-               printf("OK ]\n");
-
-       return handle;
-}
-#endif
-
-
-/* native_library_close ********************************************************
-
-   Close the native library of the given handle.
-
-   IN:
-       handle ... handle of the open library
-
-*******************************************************************************/
-
-#if defined(ENABLE_DL)
-void native_library_close(void* handle)
-{
-       int result;
-
-       if (opt_verbosejni) {
-               printf("[Unloading native library ");
-/*             utf_display_printable_ascii(filename); */
-               printf(" ... ");
-       }
-
-       /* Close the library. */
-
-       result = os_dlclose(handle);
-
-       if (result != 0) {
-               if (opt_verbose) {
-                       log_start();
-                       log_print("native_library_close: os_dlclose failed: ");
-                       log_print(dlerror());
-                       log_finish();
-               }
-       }
-}
-#endif
-
-
-/* native_library_add **********************************************************
-
-   Adds an entry to the native library hashtable.
-
-*******************************************************************************/
-
-#if defined(ENABLE_DL)
-void native_library_add(utf *filename, classloader_t *loader, void* handle)
-{
-       hashtable_library_loader_entry *le;
-       hashtable_library_name_entry   *ne; /* library name                       */
-       u4   key;                           /* hashkey                            */
-       u4   slot;                          /* slot in hashtable                  */
-
-       LOCK_MONITOR_ENTER(hashtable_library->header);
-
-       /* normally addresses are aligned to 4, 8 or 16 bytes */
-
-       key  = ((u4) (ptrint) loader) >> 4;        /* align to 16-byte boundaries */
-       slot = key & (hashtable_library->size - 1);
-       le   = hashtable_library->ptr[slot];
-
-       /* search external hash chain for the entry */
-
-       while (le) {
-               if (le->loader == loader)
-                       break;
-
-               le = le->hashlink;                  /* next element in external chain */
-       }
-
-       /* no loader found? create a new entry */
-
-       if (le == NULL) {
-               le = NEW(hashtable_library_loader_entry);
-
-               le->loader   = loader;
-               le->namelink = NULL;
-
-               /* insert entry into hashtable */
-
-               le->hashlink =
-                       (hashtable_library_loader_entry *) hashtable_library->ptr[slot];
-               hashtable_library->ptr[slot] = le;
-
-               /* update number of hashtable-entries */
-
-               hashtable_library->entries++;
-       }
-
-
-       /* search for library name */
-
-       ne = le->namelink;
-
-       while (ne) {
-               if (ne->name == filename) {
-                       LOCK_MONITOR_EXIT(hashtable_library->header);
-
-                       return;
-               }
-
-               ne = ne->hashlink;                  /* next element in external chain */
-       }
-
-       /* not found? add the library name to the classloader */
-
-       ne = NEW(hashtable_library_name_entry);
-
-       ne->name   = filename;
-       ne->handle = handle;
-
-       /* insert entry into external chain */
-
-       ne->hashlink = le->namelink;
-       le->namelink = ne;
-
-       LOCK_MONITOR_EXIT(hashtable_library->header);
-}
-#endif
-
-
-/* native_library_find *********************************************************
-
-   Find an entry in the native library hashtable.
-
-*******************************************************************************/
-
-#if defined(ENABLE_DL)
-hashtable_library_name_entry *native_library_find(utf *filename,
-                                                                                                 classloader_t *loader)
-{
-       hashtable_library_loader_entry *le;
-       hashtable_library_name_entry   *ne; /* library name                       */
-       u4   key;                           /* hashkey                            */
-       u4   slot;                          /* slot in hashtable                  */
-
-       /* normally addresses are aligned to 4, 8 or 16 bytes */
-
-       key  = ((u4) (ptrint) loader) >> 4;        /* align to 16-byte boundaries */
-       slot = key & (hashtable_library->size - 1);
-       le   = hashtable_library->ptr[slot];
-
-       /* search external hash chain for the entry */
-
-       while (le) {
-               if (le->loader == loader)
-                       break;
-
-               le = le->hashlink;                  /* next element in external chain */
-       }
-
-       /* no loader found? return NULL */
-
-       if (le == NULL)
-               return NULL;
-
-       /* search for library name */
-
-       ne = le->namelink;
-
-       while (ne) {
-               if (ne->name == filename)
-                       return ne;
-
-               ne = ne->hashlink;                  /* next element in external chain */
-       }
-
-       /* return entry, if no entry was found, ne is NULL */
-
-       return ne;
-}
-#endif
-
-
-/* native_library_load *********************************************************
-
-   Load a native library and initialize it, if possible.
-
-   IN:
-       name ... name of the library
-          cl ..... classloader which loads this library
-
-   RETURN:
-       1 ... library loaded successfully
-       0 ... error
-
-*******************************************************************************/
-
-int native_library_load(JNIEnv *env, utf *name, classloader_t *cl)
-{
-#if defined(ENABLE_DL)
-       void*   handle;
-# if defined(ENABLE_JNI)
-       void*   onload;
-       int32_t version;
-# endif
-
-       if (name == NULL) {
-               exceptions_throw_nullpointerexception();
-               return 0;
-       }
-
-       /* Is the library already loaded? */
-
-       if (native_library_find(name, cl) != NULL)
-               return 1;
-
-       /* Open the library. */
-
-       handle = native_library_open(name);
-
-       if (handle == NULL)
-               return 0;
-
-# if defined(ENABLE_JNI)
-       /* Resolve JNI_OnLoad function. */
-
-       onload = os_dlsym(handle, "JNI_OnLoad");
-
-       if (onload != NULL) {
-               JNIEXPORT int32_t (JNICALL *JNI_OnLoad) (JavaVM *, void *);
-               JavaVM *vm;
-
-               JNI_OnLoad = (JNIEXPORT int32_t (JNICALL *)(JavaVM *, void *)) (ptrint) onload;
-
-               (*env)->GetJavaVM(env, &vm);
-
-               version = JNI_OnLoad(vm, NULL);
-
-               /* If the version is not 1.2 and not 1.4 the library cannot be
-                  loaded. */
-
-               if ((version != JNI_VERSION_1_2) && (version != JNI_VERSION_1_4)) {
-                       os_dlclose(handle);
-                       return 0;
-               }
-       }
-# endif
-
-       /* Insert the library name into the library hash. */
-
-       native_library_add(name, cl, handle);
-
-       return 1;
-#else
-       vm_abort("native_library_load: not available");
-
-       /* Keep compiler happy. */
-
-       return 0;
-#endif
-}
-
-
-/* native_new_and_init *********************************************************
-
-   Creates a new object on the heap and calls the initializer.
-   Returns the object pointer or NULL if memory is exhausted.
-                       
-*******************************************************************************/
-
-java_handle_t *native_new_and_init(classinfo *c)
-{
-       methodinfo    *m;
-       java_handle_t *o;
-
-       if (c == NULL)
-               vm_abort("native_new_and_init: c == NULL");
-
-       /* create object */
-
-       o = builtin_new(c);
-       
-       if (o == NULL)
-               return NULL;
-
-       /* try to find the initializer */
-
-       m = class_findmethod(c, utf_init, utf_void__void);
-                                                     
-       /* ATTENTION: returning the object here is ok, since the class may
-       not have an initializer */
-
-       if (m == NULL)
-               return o;
-
-       /* call initializer */
-
-       (void) vm_call_method(m, o);
-
-       return o;
-}
-
-
-java_handle_t *native_new_and_init_string(classinfo *c, java_handle_t *s)
-{
-       methodinfo    *m;
-       java_handle_t *o;
-
-       if (c == NULL)
-               vm_abort("native_new_and_init_string: c == NULL");
-
-       /* create object */
-
-       o = builtin_new(c);
-
-       if (o == NULL)
-               return NULL;
-
-       /* find initializer */
-
-       m = class_findmethod(c, utf_init, utf_java_lang_String__void);
-
-       /* initializer not found */
-
-       if (m == NULL)
-               return NULL;
-
-       /* call initializer */
-
-       (void) vm_call_method(m, o, s);
-
-       return o;
-}
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
diff --git a/src/native/native.cpp b/src/native/native.cpp
new file mode 100644 (file)
index 0000000..89a530c
--- /dev/null
@@ -0,0 +1,814 @@
+/* src/native/native.cpp - native library support
+
+   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 <ctype.h>
+
+#include <stdint.h>
+
+#include <algorithm>
+#include <functional>
+#include <map>
+
+#include "mm/memory.h"
+
+#include "native/jni.hpp"
+#include "native/native.hpp"
+
+#include "threads/mutex.hpp"
+
+#include "toolbox/logging.h"
+
+#include "vm/jit/builtin.hpp"
+#include "vm/exceptions.hpp"
+#include "vm/global.h"
+#include "vm/globals.hpp"
+#include "vm/loader.hpp"
+#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.hpp"
+
+#if defined(ENABLE_JVMTI)
+#include "native/jvmti/cacaodbg.h"
+#endif
+
+
+/* native_make_overloaded_function *********************************************
+
+   XXX
+
+*******************************************************************************/
+
+static utf *native_make_overloaded_function(utf *name, utf *descriptor)
+{
+       char *newname;
+       s4    namelen;
+       char *utf_ptr;
+       u2    c;
+       s4    i;
+       utf  *u;
+
+       utf_ptr = descriptor->text;
+       namelen = strlen(name->text) + strlen("__") + strlen("0");
+
+       /* calculate additional length */
+
+       while ((c = utf_nextu2(&utf_ptr)) != ')') {
+               switch (c) {
+               case 'Z':
+               case 'B':
+               case 'C':
+               case 'S':
+               case 'I':
+               case 'J':
+               case 'F':
+               case 'D':
+                       namelen++;
+                       break;
+               case '[':
+                       namelen += 2;
+                       break;
+               case 'L':
+                       namelen++;
+                       while (utf_nextu2(&utf_ptr) != ';')
+                               namelen++;
+                       namelen += 2;
+                       break;
+               case '(':
+                       break;
+               default:
+                       assert(0);
+               }
+       }
+
+       /* reallocate memory */
+
+       i = strlen(name->text);
+
+       newname = MNEW(char, namelen);
+       MCOPY(newname, name->text, char, i);
+
+       utf_ptr = descriptor->text;
+
+       newname[i++] = '_';
+       newname[i++] = '_';
+
+       while ((c = utf_nextu2(&utf_ptr)) != ')') {
+               switch (c) {
+               case 'Z':
+               case 'B':
+               case 'C':
+               case 'S':
+               case 'J':
+               case 'I':
+               case 'F':
+               case 'D':
+                       newname[i++] = c;
+                       break;
+               case '[':
+                       newname[i++] = '_';
+                       newname[i++] = '3';
+                       break;
+               case 'L':
+                       newname[i++] = 'L';
+                       while ((c = utf_nextu2(&utf_ptr)) != ';')
+                               if (((c >= 'a') && (c <= 'z')) ||
+                                       ((c >= 'A') && (c <= 'Z')) ||
+                                       ((c >= '0') && (c <= '9')))
+                                       newname[i++] = c;
+                               else
+                                       newname[i++] = '_';
+                       newname[i++] = '_';
+                       newname[i++] = '2';
+                       break;
+               case '(':
+                       break;
+               default:
+                       assert(0);
+               }
+       }
+
+       /* close string */
+
+       newname[i] = '\0';
+
+       /* make a utf-string */
+
+       u = utf_new_char(newname);
+
+       /* release memory */
+
+       MFREE(newname, char, namelen);
+
+       return u;
+}
+
+
+/* native_insert_char **********************************************************
+
+   Inserts the passed UTF character into the native method name.  If
+   necessary it is escaped properly.
+
+*******************************************************************************/
+
+static s4 native_insert_char(char *name, u4 pos, u2 c)
+{
+       s4 val;
+       s4 i;
+
+       switch (c) {
+       case '/':
+       case '.':
+               /* replace '/' or '.' with '_' */
+               name[pos] = '_';
+               break;
+
+       case '_':
+               /* escape sequence for '_' is '_1' */
+               name[pos]   = '_';
+               name[++pos] = '1';
+               break;
+
+       case ';':
+               /* escape sequence for ';' is '_2' */
+               name[pos]   = '_';
+               name[++pos] = '2';
+               break;
+
+       case '[':
+               /* escape sequence for '[' is '_1' */
+               name[pos]   = '_';
+               name[++pos] = '3';
+               break;
+
+       default:
+               if (isalnum(c))
+                       name[pos] = c;
+               else {
+                       /* unicode character */
+                       name[pos]   = '_';
+                       name[++pos] = '0';
+
+                       for (i = 0; i < 4; ++i) {
+                               val = c & 0x0f;
+                               name[pos + 4 - i] = (val > 10) ? ('a' + val - 10) : ('0' + val);
+                               c >>= 4;
+                       }
+
+                       pos += 4;
+               }
+               break;
+       }
+
+       /* return the new buffer index */
+
+       return pos;
+}
+
+
+/* native_method_symbol ********************************************************
+
+   Generate a method-symbol string out of the class name and the
+   method name.
+
+*******************************************************************************/
+
+static utf *native_method_symbol(utf *classname, utf *methodname)
+{
+       char *name;
+       s4    namelen;
+       char *utf_ptr;
+       char *utf_endptr;
+       u2    c;
+       u4    pos;
+       utf  *u;
+
+       /* Calculate length of native function name.  We multiply the
+          class and method name length by 6 as this is the maxium
+          escape-sequence that can be generated (unicode). */
+
+       namelen =
+               strlen("Java_") +
+               utf_get_number_of_u2s(classname) * 6 +
+               strlen("_") +
+               utf_get_number_of_u2s(methodname) * 6 +
+               strlen("0");
+
+       /* allocate memory */
+
+       name = MNEW(char, namelen);
+
+       /* generate name of native functions */
+
+       strcpy(name, "Java_");
+       pos = strlen("Java_");
+
+       utf_ptr    = classname->text;
+       utf_endptr = UTF_END(classname);
+
+       for (; utf_ptr < utf_endptr; utf_ptr++, pos++) {
+               c   = *utf_ptr;
+               pos = native_insert_char(name, pos, c);
+       }
+
+       /* seperator between class and method */
+
+       name[pos++] = '_';
+
+       utf_ptr    = methodname->text;
+       utf_endptr = UTF_END(methodname);
+
+       for (; utf_ptr < utf_endptr; utf_ptr++, pos++) {
+               c   = *utf_ptr;
+               pos = native_insert_char(name, pos, c);
+       }
+
+       /* close string */
+
+       name[pos] = '\0';
+
+       /* check for an buffer overflow */
+
+       assert((int32_t) pos <= namelen);
+
+       /* make a utf-string */
+
+       u = utf_new_char(name);
+
+       /* release memory */
+
+       MFREE(name, char, namelen);
+
+       return u;
+}
+
+
+bool operator< (const NativeMethod& first, const NativeMethod& second)
+{
+       if (first._classname < second._classname)
+               return true;
+       else if (first._classname > second._classname)
+               return false;
+               
+       if (first._name < second._name)
+               return true;
+       else if (first._name > second._name)
+               return false;
+
+       if (first._descriptor < second._descriptor)
+               return true;
+       else if (first._descriptor > second._descriptor)
+               return false;
+
+       // All pointers are equal, we have found the entry.
+       return false;
+}
+
+
+/**
+ * Register native methods with the VM.  This is done by inserting
+ * them into the native method table.
+ *
+ * @param classname
+ * @param methods   Native methods array.
+ * @param count     Number of methods in the array.
+ */
+void NativeMethods::register_methods(utf* classname, const JNINativeMethod* methods, size_t count)
+{
+       // Insert all methods passed */
+       for (size_t i = 0; i < count; i++) {
+               if (opt_verbosejni) {
+                       printf("[Registering JNI native method ");
+                       utf_display_printable_ascii_classname(classname);
+                       printf(".%s]\n", methods[i].name);
+               }
+
+               // Generate the UTF8 names.
+               utf* name      = utf_new_char(methods[i].name);
+               utf* signature = utf_new_char(methods[i].signature);
+
+               NativeMethod nm(classname, name, signature, methods[i].fnPtr);
+
+               // Insert the method into the table.
+               _methods.insert(nm);
+       }
+}
+
+
+/**
+ * Resolves a native method, maybe from a dynamic library.
+ *
+ * @param m Method structure of the native Java method to resolve.
+ *
+ * @return Pointer to the resolved method (symbol).
+ */
+void* NativeMethods::resolve_method(methodinfo* m)
+{
+       // Verbose output.
+       if (opt_verbosejni) {
+               printf("[Dynamic-linking native method ");
+               utf_display_printable_ascii_classname(m->clazz->name);
+               printf(".");
+               utf_display_printable_ascii(m->name);
+               printf(" ... ");
+       }
+
+       /* generate method symbol string */
+
+       utf* name = native_method_symbol(m->clazz->name, m->name);
+
+       /* generate overloaded function (having the types in it's name)           */
+
+       utf* newname = native_make_overloaded_function(name, m->descriptor);
+
+       // Try to find the symbol.
+       void* symbol = NULL;
+
+#if defined(ENABLE_DL)
+       // Get the classloader.
+       classloader_t* classloader = class_get_classloader(m->clazz);
+
+       // Resolve the native method name from the native libraries.
+       NativeLibraries& libraries = VM::get_current()->get_nativelibraries();
+       symbol = libraries.resolve_symbol(name, classloader);
+
+       if (symbol == NULL)
+               symbol = libraries.resolve_symbol(newname, classloader);
+
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+       if (symbol == NULL) {
+               /* We can resolve the function directly from
+                  java.lang.ClassLoader as it's a static function. */
+               /* XXX should be done in native_init */
+
+               methodinfo* method_findNative =
+                       class_resolveclassmethod(class_java_lang_ClassLoader,
+                                                                        utf_findNative,
+                                                                        utf_java_lang_ClassLoader_java_lang_String__J,
+                                                                        class_java_lang_ClassLoader,
+                                                                        true);
+
+               if (method_findNative == NULL)
+                       return NULL;
+
+               // Try the normal name.
+               java_handle_t* s = javastring_new(name);
+               symbol = (void*) vm_call_method_long(method_findNative, NULL, classloader, s);
+
+               // If not found, try the mangled name.
+               if (symbol == NULL) {
+                       s = javastring_new(newname);
+                       symbol = (void*) vm_call_method_long(method_findNative, NULL, classloader, s);
+               }
+       }
+# endif
+
+       if (symbol != NULL)
+               if (opt_verbosejni)
+                       printf("JNI ]\n");
+#endif
+
+       // If not found already, try to find the native method symbol in
+       // the native methods registered with the VM.
+       if (symbol == NULL) {
+               symbol = find_registered_method(m);
+
+               if (symbol != NULL)
+                       if (opt_verbosejni)
+                               printf("internal ]\n");
+       }
+
+#if defined(ENABLE_JVMTI)
+       /* fire Native Method Bind event */
+       if (jvmti) jvmti_NativeMethodBind(m, f, &f);
+#endif
+
+       // Symbol not found?  Throw an exception.
+       if (symbol == NULL) {
+               if (opt_verbosejni)
+                       printf("failed ]\n");
+
+               exceptions_throw_unsatisfiedlinkerror(m->name);
+       }
+
+       return symbol;
+}
+
+
+/**
+ * Try to find the given method in the native methods registered with
+ * the VM.
+ *
+ * @param m Method structure.
+ *
+ * @return Pointer to function if found, NULL otherwise.
+ */
+void* NativeMethods::find_registered_method(methodinfo* m)
+{
+       NativeMethod nm(m);
+       std::set<NativeMethod>::iterator it = _methods.find(nm);
+
+       if (it == _methods.end())
+               return NULL;
+
+       return (*it).get_function();
+}
+
+
+/**
+ * Open this native library.
+ *
+ * @return File handle on success, NULL otherwise.
+ */
+#if defined(ENABLE_DL)
+void* NativeLibrary::open()
+{
+       if (opt_verbosejni) {
+               printf("[Loading native library ");
+               utf_display_printable_ascii(_filename);
+               printf(" ... ");
+       }
+
+       // Sanity check.
+       assert(_filename != NULL);
+
+       // Try to open the library.
+       _handle = os::dlopen(_filename->text, RTLD_LAZY);
+
+       if (_handle == NULL) {
+               if (opt_verbosejni)
+                       printf("failed ]\n");
+
+               if (opt_verbose) {
+                       log_start();
+                       log_print("NativeLibrary::open: os::dlopen failed: ");
+                       log_print(os::dlerror());
+                       log_finish();
+               }
+
+               return NULL;
+       }
+
+       if (opt_verbosejni)
+               printf("OK ]\n");
+
+       return _handle;
+}
+#endif
+
+
+/**
+ * Close this native library.
+ */
+#if defined(ENABLE_DL)
+void NativeLibrary::close()
+{
+       if (opt_verbosejni) {
+               printf("[Unloading native library ");
+/*             utf_display_printable_ascii(filename); */
+               printf(" ... ");
+       }
+
+       // Sanity check.
+       assert(_handle != NULL);
+
+       // Close the library.
+       int result = os::dlclose(_handle);
+
+       if (result != 0) {
+               if (opt_verbosejni)
+                       printf("failed ]\n");
+
+               if (opt_verbose) {
+                       log_start();
+                       log_print("NativeLibrary::close: os::dlclose failed: ");
+                       log_print(os::dlerror());
+                       log_finish();
+               }
+       }
+
+       if (opt_verbosejni)
+               printf("OK ]\n");
+}
+#endif
+
+
+/**
+ * Load this native library and initialize it, if possible.
+ *
+ * @param env JNI environment.
+ *
+ * @return true if library loaded successfully, false otherwise.
+ */
+bool NativeLibrary::load(JNIEnv* env)
+{
+#if defined(ENABLE_DL)
+       if (_filename == NULL) {
+               exceptions_throw_nullpointerexception();
+               return false;
+       }
+
+       // Is the library already loaded?
+       if (is_loaded())
+               return true;
+
+       // Open the library.
+       open();
+
+       if (_handle == NULL)
+               return false;
+
+# if defined(ENABLE_JNI)
+       // Resolve JNI_OnLoad function.
+       void* onload = os::dlsym(_handle, "JNI_OnLoad");
+
+       if (onload != NULL) {
+               JNIEXPORT jint (JNICALL *JNI_OnLoad) (JavaVM*, void*);
+               JavaVM *vm;
+
+               JNI_OnLoad = (JNIEXPORT jint (JNICALL *)(JavaVM*, void*)) (uintptr_t) onload;
+
+               env->GetJavaVM(&vm);
+
+               jint version = JNI_OnLoad(vm, NULL);
+
+               // If the version is not 1.2 and not 1.4 the library cannot be
+               // loaded.
+               if ((version != JNI_VERSION_1_2) && (version != JNI_VERSION_1_4)) {
+                       os::dlclose(_handle);
+                       return false;
+               }
+       }
+# endif
+
+       // Insert the library name into the native library table.
+       NativeLibraries& nativelibraries = VM::get_current()->get_nativelibraries();
+       nativelibraries.add(*this);
+
+       return true;
+#else
+       os::abort("NativeLibrary::load: Not available in this configuration.");
+
+       // Keep the compiler happy.
+       return false;
+#endif
+}
+
+
+/**
+ * Checks if this native library is loaded.
+ *
+ * @return true if loaded, false otherwise.
+ */
+#if defined(ENABLE_DL)
+bool NativeLibrary::is_loaded()
+{
+       NativeLibraries& libraries = VM::get_current()->get_nativelibraries();
+       return libraries.is_loaded(*this);
+}
+#endif
+
+
+/**
+ * Resolve the given symbol in this native library.
+ *
+ * @param symbolname Symbol name.
+ *
+ * @return Pointer to symbol if found, NULL otherwise.
+ */
+void* NativeLibrary::resolve_symbol(utf* symbolname) const
+{
+       return os::dlsym(_handle, symbolname->text);
+}
+
+
+/**
+ * Add the given native library to the native libraries table.
+ *
+ * @param library Native library to insert.
+ */
+#if defined(ENABLE_DL)
+void NativeLibraries::add(NativeLibrary& library)
+{
+       // Make the container thread-safe.
+       _mutex.lock();
+
+       // XXX Check for double entries.
+       // Insert the native library.
+       _libraries.insert(std::make_pair(library.get_classloader(), library));
+
+       _mutex.unlock();
+}
+#endif
+
+
+/**
+ * Checks if the given native library is loaded.
+ *
+ * @param library Native library.
+ *
+ * @return true if loaded, false otherwise.
+ */
+bool NativeLibraries::is_loaded(NativeLibrary& library)
+{
+       std::pair<MAP::const_iterator, MAP::const_iterator> its = _libraries.equal_range(library.get_classloader());
+
+       // No entry for the classloader was found (the range has length
+       // zero).
+       if (its.first == its.second)
+               return false;
+       
+       MAP::const_iterator it = find_if(its.first, its.second, std::bind2nd(comparator(), library.get_filename()));
+
+       // No matching entry in the range found.
+       if (it == its.second)
+               return false;
+
+       return true;
+}
+
+
+/**
+ * Try to find a symbol with the given name in all loaded native
+ * libraries defined by classloader.
+ *
+ * @param symbolname  Name of the symbol to find.
+ * @param classloader Defining classloader.
+ *
+ * @return Pointer to symbol if found, NULL otherwise.
+ */
+void* NativeLibraries::resolve_symbol(utf* symbolname, classloader_t* classloader)
+{
+       std::pair<MAP::const_iterator, MAP::const_iterator> its = _libraries.equal_range(classloader);
+
+       // No entry for the classloader was found (the range has length
+       // zero).
+       if (its.first == its.second)
+               return NULL;
+
+       for (MAP::const_iterator it = its.first; it != its.second; it++) {
+               const NativeLibrary& library = (*it).second;
+               void* symbol = library.resolve_symbol(symbolname);
+
+               if (symbol != NULL)
+                       return symbol;
+       }
+
+       return NULL;
+}
+
+
+/* native_new_and_init *********************************************************
+
+   Creates a new object on the heap and calls the initializer.
+   Returns the object pointer or NULL if memory is exhausted.
+                       
+*******************************************************************************/
+
+java_handle_t *native_new_and_init(classinfo *c)
+{
+       methodinfo    *m;
+       java_handle_t *o;
+
+       if (c == NULL)
+               vm_abort("native_new_and_init: c == NULL");
+
+       /* create object */
+
+       o = builtin_new(c);
+       
+       if (o == NULL)
+               return NULL;
+
+       /* try to find the initializer */
+
+       m = class_findmethod(c, utf_init, utf_void__void);
+                                                     
+       /* ATTENTION: returning the object here is ok, since the class may
+       not have an initializer */
+
+       if (m == NULL)
+               return o;
+
+       /* call initializer */
+
+       (void) vm_call_method(m, o);
+
+       return o;
+}
+
+
+java_handle_t *native_new_and_init_string(classinfo *c, java_handle_t *s)
+{
+       methodinfo    *m;
+       java_handle_t *o;
+
+       if (c == NULL)
+               vm_abort("native_new_and_init_string: c == NULL");
+
+       /* create object */
+
+       o = builtin_new(c);
+
+       if (o == NULL)
+               return NULL;
+
+       /* find initializer */
+
+       m = class_findmethod(c, utf_init, utf_java_lang_String__void);
+
+       /* initializer not found */
+
+       if (m == NULL)
+               return NULL;
+
+       /* call initializer */
+
+       (void) vm_call_method(m, o, s);
+
+       return o;
+}
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
diff --git a/src/native/native.h b/src/native/native.h
deleted file mode 100644 (file)
index a2d3556..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-/* src/native/native.h - native library support
-
-   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 _NATIVE_H
-#define _NATIVE_H
-
-#include "config.h"
-
-#include <stdint.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "native/jni.h"
-
-#include "vm/class.h"
-#include "vm/global.h"
-#include "vm/loader.h"
-#include "vm/method.h"
-#include "vm/os.hpp"
-#include "vm/utf8.h"
-
-
-/* defines ********************************************************************/
-
-#define NATIVE_METHODS_COUNT    sizeof(methods) / sizeof(JNINativeMethod)
-
-
-#define NATIVE_LIBRARY_PREFIX     "lib"
-
-#if defined(__DARWIN__)
-# define NATIVE_LIBRARY_SUFFIX    ".dylib"
-#else
-# define NATIVE_LIBRARY_SUFFIX    ".so"
-#endif
-
-
-/* native_methods_node_t ******************************************************/
-
-typedef struct native_methods_node_t native_methods_node_t;
-
-struct native_methods_node_t {
-       utf         *classname;             /* class name                         */
-       utf         *name;                  /* method name                        */
-       utf         *descriptor;            /* descriptor name                    */
-       functionptr  function;              /* pointer to the implementation      */
-};
-
-
-/* hashtable_library_loader_entry *********************************************/
-
-#if defined(ENABLE_DL)
-typedef struct hashtable_library_loader_entry hashtable_library_loader_entry;
-typedef struct hashtable_library_name_entry   hashtable_library_name_entry;
-
-struct hashtable_library_loader_entry {
-       classloader_t                  *loader;  /* class loader                  */
-       hashtable_library_name_entry   *namelink;/* libs loaded by this loader    */
-       hashtable_library_loader_entry *hashlink;/* link for external chaining    */
-};
-#endif
-
-
-/* hashtable_library_name_entry ***********************************************/
-
-#if defined(ENABLE_DL)
-struct hashtable_library_name_entry {
-       utf                          *name;      /* library name                  */
-       void*                         handle;    /* libtool library handle        */
-       hashtable_library_name_entry *hashlink;  /* link for external chaining    */
-};
-#endif
-
-
-/* function prototypes ********************************************************/
-
-bool native_init(void);
-
-void        native_method_register(utf *classname, const JNINativeMethod *methods, int32_t count);
-functionptr native_method_resolve(methodinfo *m);
-
-#if defined(ENABLE_DL)
-void*       native_library_open(utf *filename);
-void        native_library_close(void* handle);
-void        native_library_add(utf *filename, classloader_t *loader, void *handle);
-hashtable_library_name_entry *native_library_find(utf *filename, classloader_t *loader);
-int         native_library_load(JNIEnv *env, utf *name, classloader_t *cl);
-#endif
-
-java_handle_t *native_new_and_init(classinfo *c);
-java_handle_t *native_new_and_init_string(classinfo *c, java_handle_t *s);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _NATIVE_H */
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
diff --git a/src/native/native.hpp b/src/native/native.hpp
new file mode 100644 (file)
index 0000000..c0b4cda
--- /dev/null
@@ -0,0 +1,190 @@
+/* src/native/native.hpp - native library support
+
+   Copyright (C) 1996-2005, 2006, 2007, 2008
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+   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 _NATIVE_HPP
+#define _NATIVE_HPP
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+#include <map>
+#include <set>
+#endif
+
+#include "native/jni.hpp"
+
+#include "vm/class.h"
+#include "vm/global.h"
+#include "vm/loader.hpp"
+#include "vm/method.h"
+#include "vm/os.hpp"
+#include "vm/utf8.h"
+
+
+/* defines ********************************************************************/
+
+#define NATIVE_METHODS_COUNT    sizeof(methods) / sizeof(JNINativeMethod)
+
+
+#define NATIVE_LIBRARY_PREFIX     "lib"
+
+#if defined(__DARWIN__)
+# define NATIVE_LIBRARY_SUFFIX    ".dylib"
+#else
+# define NATIVE_LIBRARY_SUFFIX    ".so"
+#endif
+
+
+#ifdef __cplusplus
+
+#if defined(ENABLE_DL)
+/**
+ * Represents a native library.
+ */
+class NativeLibrary {
+private:
+       utf*           _filename;    ///< Name of the native library.
+       classloader_t* _classloader; ///< Defining classloader.
+       void*          _handle;      ///< Filesystem handle.
+
+public:
+       NativeLibrary(utf* filename, classloader_t* classloader = 0, void* handle = 0) : _filename(filename), _classloader(classloader), _handle(handle) {}
+       NativeLibrary(void* handle) : _filename(0), _classloader(0), _handle(handle) {}
+
+       inline classloader_t* get_classloader() const { return _classloader; }
+       inline utf*           get_filename   () const { return _filename; }
+       inline void*          get_handle     () const { return _handle; }
+
+       void* open();
+       void  close();
+       bool  load(JNIEnv* env);
+       bool  is_loaded();
+       void* resolve_symbol(utf* symbolname) const;
+};
+
+
+/**
+ * Table containing all loaded native libraries.
+ */
+class NativeLibraries {
+private:
+       Mutex _mutex; ///< Mutex to make the container thread-safe.
+       typedef std::multimap<classloader_t*, NativeLibrary> MAP;
+       MAP _libraries;
+
+private:
+       // Comparator class.
+       class comparator : public std::binary_function<std::pair<classloader_t*, NativeLibrary>, utf*, bool> {
+       public:
+               bool operator() (std::pair<classloader_t*, NativeLibrary> args, const utf* filename) const
+               {
+                       return (args.second.get_filename() == filename);
+               }
+       };
+
+public:
+       void  add(NativeLibrary& library);
+       bool  is_loaded(NativeLibrary& library);
+       void* resolve_symbol(utf* symbolname, classloader_t* classloader);
+};
+#endif
+
+
+/**
+ * Represents a native method.
+ */
+class NativeMethod {
+private:
+       utf*  _classname;  ///< Class name.
+       utf*  _name;       ///< Method name.
+       utf*  _descriptor; ///< Method signature.
+       void* _function;   ///< Pointer to the native function.
+
+       friend bool operator< (const NativeMethod& first, const NativeMethod& second);
+
+public:
+       NativeMethod(utf* classname, utf* name, utf* signature, void* function) : _classname(classname), _name(name), _descriptor(signature), _function(function) {}
+       NativeMethod(methodinfo* m) : _classname(m->clazz->name), _name(m->name), _descriptor(m->descriptor), _function(0) {}
+
+       inline void* get_function() const { return _function; }
+};
+
+
+/**
+ * Table containing all native methods registered with the VM.
+ */
+class NativeMethods {
+private:
+       Mutex _mutex;
+       std::set<NativeMethod> _methods;
+
+private:
+       // Comparator class.
+       class comparator : public std::binary_function<std::pair<classloader_t*, NativeLibrary>, utf*, bool> {
+       public:
+               bool operator() (std::pair<classloader_t*, NativeLibrary> args, const utf* filename) const
+               {
+                       return (args.second.get_filename() == filename);
+               }
+       };
+       
+public:
+       void  register_methods(utf* classname, const JNINativeMethod* methods, size_t count);
+       void* resolve_method(methodinfo* m);
+       void* find_registered_method(methodinfo* m);
+};
+
+#endif
+
+/* function prototypes ********************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+java_handle_t *native_new_and_init(classinfo *c);
+java_handle_t *native_new_and_init_string(classinfo *c, java_handle_t *s);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _NATIVE_HPP
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
index f819ead808e5c7a9f5e773810846a6e11ba59614..f7f843f7a213a03c7f5a3d8eb8dd86549317179e 100644 (file)
@@ -56,8 +56,8 @@ endif
 
 if ENABLE_JAVASE
 REFLECTION_SOURCES = \
-       reflection.c \
-       reflection.h
+       reflection.cpp \
+       reflection.hpp
 
 SUN_MISC_UNSAFE_SOURCES = \
        sun_misc_Unsafe.cpp
@@ -67,8 +67,8 @@ noinst_LTLIBRARIES = \
        libnativevm.la
 
 libnativevm_la_SOURCES = \
-       nativevm.c \
-       nativevm.h \
+       nativevm.cpp \
+       nativevm.hpp \
        $(REFLECTION_SOURCES) \
        $(SUN_MISC_UNSAFE_SOURCES)
 
index a262ca46fadd8fc70b4940ee97bbfef50b447392..3d53b2cbf52e5d11e6f9f20984500dcf315e50f5 100644 (file)
 
 #include "mm/memory.h"
 
-#include "native/jni.h"
+#include "native/jni.hpp"
 #include "native/llni.h"
-#include "native/native.h"
+#include "native/native.hpp"
 
 #if defined(ENABLE_JNI_HEADERS)
 # include "native/include/com_sun_cldc_io_ResourceInputStream.h"
 #endif
 
-#include "threads/lock-common.h"
+#include "threads/mutex.hpp"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/exceptions.hpp"
 #include "vm/javaobjects.hpp"
 #include "vm/string.hpp"
@@ -188,7 +188,6 @@ extern "C" {
  */
 JNIEXPORT jobject JNICALL Java_com_sun_cldc_io_ResourceInputStream_open(JNIEnv *env, jclass clazz, jstring name)
 {
-       list_classpath_entry *lce;
        char *filename;
        s4 filenamelen;
        char *path;
@@ -205,20 +204,20 @@ JNIEXPORT jobject JNICALL Java_com_sun_cldc_io_ResourceInputStream_open(JNIEnv *
        
        /* walk through all classpath entries */
 
-       for (lce = (list_classpath_entry*) list_first(list_classpath_entries); lce != NULL;
-                lce = (list_classpath_entry*) list_next(list_classpath_entries, lce)) {
-                       
+       for (List<list_classpath_entry*>::iterator it = list_classpath_entries->begin(); it != list_classpath_entries->end(); it++) {
+               list_classpath_entry* lce = *it;
+
 #if defined(ENABLE_ZLIB)
                if (lce->type == CLASSPATH_ARCHIVE) {
 
                        /* enter a monitor on zip/jar archives */
-                       LOCK_MONITOR_ENTER(lce);
+                       lce->mutex->lock();
 
                        /* try to get the file in current archive */
                        descriptor = zip_read_resource(lce, uname);
 
                        /* leave the monitor */
-                       LOCK_MONITOR_EXIT(lce);
+                       lce->mutex->unlock();
                        
                        if (descriptor != NULL) { /* file exists */
                                break;
@@ -376,16 +375,12 @@ static JNINativeMethod methods[] = {
  
 *******************************************************************************/
  
-// FIXME
-extern "C" {
 void _Jv_com_sun_cldc_io_ResourceInputStream_init(void)
 {
-       utf *u;
+       utf* u = utf_new_char("com/sun/cldc/io/ResourceInputStream");
  
-       u = utf_new_char("com/sun/cldc/io/ResourceInputStream");
-       native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+       NativeMethods& nm = VM::get_current()->get_nativemethods();
+       nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
 }
 
 
index 9373b6b92f9650ab7300af230bbde22ab5f4e27e..9ad7f7c206d258eb6d074778a4b3ea8c0de0998a 100644 (file)
@@ -36,9 +36,9 @@
 
 #include "mm/memory.h"
 
-#include "native/jni.h"
+#include "native/jni.hpp"
 #include "native/llni.h"
-#include "native/native.h"
+#include "native/native.hpp"
 
 #if defined(ENABLE_JNI_HEADERS)
 # include "native/include/com_sun_cldc_io_j2me_socket_Protocol.h"
@@ -238,16 +238,12 @@ static JNINativeMethod methods[] = {
  
 *******************************************************************************/
  
-// FIXME
-extern "C" {
 void _Jv_com_sun_cldc_io_j2me_socket_Protocol_init(void)
 {
-       utf *u;
-       u = utf_new_char("com/sun/cldc/io/j2me/socket/Protocol");
+       utf* u = utf_new_char("com/sun/cldc/io/j2me/socket/Protocol");
  
-       native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+       NativeMethods& nm = VM::get_current()->get_nativemethods();
+       nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
 }
 
 
index 8fcae40d78ef7300007d0999a06c7fa6f33f8a4d..96aeb015888364b25596d2f66fffe3cc7ff71b08 100644 (file)
 
 #include "vm/types.h"
 
-#include "native/jni.h"
-#include "native/native.h"
+#include "native/jni.hpp"
+#include "native/native.hpp"
 
 #if defined(ENABLE_JNI_HEADERS)
 # include "native/include/com_sun_cldchi_io_ConsoleOutputStream.h"
 #endif
 
+#include "vm/vm.hpp"
+
 
 // Native functions are exported as C functions.
 extern "C" {
@@ -67,16 +69,12 @@ static JNINativeMethod methods[] = {
  
 *******************************************************************************/
  
-// FIXME
-extern "C" { 
 void _Jv_com_sun_cldchi_io_ConsoleOutputStream_init(void)
 {
-       utf *u;
-       u = utf_new_char("com/sun/cldchi/io/ConsoleOutputStream");
+       utf* u = utf_new_char("com/sun/cldchi/io/ConsoleOutputStream");
  
-       native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+       NativeMethods& nm = VM::get_current()->get_nativemethods();
+       nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
 }
 
 
index 3416c45c6891cdff512ccae695fc5ef15c957f21..69acdddbf8c80dd2c68c4e58558039a71e15d2fe 100644 (file)
@@ -27,8 +27,8 @@
 
 #include <stdint.h>
 
-#include "native/jni.h"
-#include "native/native.h"
+#include "native/jni.hpp"
+#include "native/native.hpp"
 
 #if defined(ENABLE_JNI_HEADERS)
 # include "native/include/com_sun_cldchi_jvm_JVM.h"
@@ -36,6 +36,7 @@
 
 #include "vm/exceptions.hpp"
 #include "vm/string.hpp"
+#include "vm/vm.hpp"
 
 
 // Native functions are exported as C functions.
@@ -53,15 +54,14 @@ JNIEXPORT void JNICALL Java_com_sun_cldchi_jvm_JVM_loadLibrary(JNIEnv *env, jcla
                return;
        }
 
-       /* REMOVEME When we use Java-strings internally. */
+       // REMOVEME When we use Java-strings internally.
+       utf* name = javastring_toutf((java_handle_t*) libName, false);
 
-       utf* name = javastring_toutf((java_handle_t *) libName, false);
+       NativeLibrary nl(name);
+       bool result = nl.load(env);
 
-       int result = native_library_load(env, name, NULL);
-
-       /* Check for error and throw an exception in case. */
-
-       if (result == 0) {
+       // Check for error and throw an exception in case.
+       if (result == false) {
                exceptions_throw_unsatisfiedlinkerror(name);
        }
 }
@@ -82,16 +82,12 @@ static JNINativeMethod methods[] = {
  
 *******************************************************************************/
  
-// FIXME
-extern "C" { 
 void _Jv_com_sun_cldchi_jvm_JVM_init(void)
 {
-       utf *u;
+       utf* u = utf_new_char("com/sun/cldchi/jvm/JVM");
  
-       u = utf_new_char("com/sun/cldchi/jvm/JVM");
-       native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+       NativeMethods& nm = VM::get_current()->get_nativemethods();
+       nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
 }
 
 
index 49d459da799f5b20e1c3626e4e38a8a9c440745c..a5d928dd78679e21e069443a72633cfc332b1095 100644 (file)
@@ -27,9 +27,9 @@
 
 #include <stdint.h>
 
-#include "native/jni.h"
+#include "native/jni.hpp"
 #include "native/llni.h"
-#include "native/native.h"
+#include "native/native.hpp"
 
 #if defined(ENABLE_JNI_HEADERS)
 # include "native/include/java_lang_Class.h"
@@ -214,22 +214,19 @@ static JNINativeMethod methods[] = {
        { (char*) "getName",          (char*) "()Ljava/lang/String;",                 (void*) (uintptr_t) &Java_java_lang_Class_getName          },
 };
 
+
 /* _Jv_java_lang_Class_init ****************************************************
  
    Register native functions.
  
 *******************************************************************************/
 
-// FIXME
-extern "C" { 
 void _Jv_java_lang_Class_init(void)
 {
-       utf *u;
-       u = utf_new_char("java/lang/Class");
+       utf* u = utf_new_char("java/lang/Class");
  
-       native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+       NativeMethods& nm = VM::get_current()->get_nativemethods();
+       nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
 }
 
 
index 772b603caa62d89473b6ba4d1b965fe8cf526fa3..6f5f701b3ffe3ba4d10c0ac65d72620635118ee9 100644 (file)
 
 #include <stdint.h>
 
-#include "native/jni.h"
-#include "native/native.h"
+#include "native/jni.hpp"
+#include "native/native.hpp"
 
 #if defined(ENABLE_JNI_HEADERS)
 # include "native/include/java_lang_Double.h"
 #endif
 
-#include "vm/builtin.h"
+#include "vm/vm.hpp"
+
+#include "vm/jit/builtin.hpp"
 
 
 // Native functions are exported as C functions.
@@ -105,16 +107,12 @@ static JNINativeMethod methods[] = {
  
 *******************************************************************************/
 
-// FIXME
-extern "C" { 
 void _Jv_java_lang_Double_init(void)
 {
-       utf *u;
-       u = utf_new_char("java/lang/Double");
+       utf* u = utf_new_char("java/lang/Double");
  
-       native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+       NativeMethods& nm = VM::get_current()->get_nativemethods();
+       nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
 }
 
 
index bea50c0c5fac47cea35e91545de5b2946904dc22..9d521e2a18c5f23225074b5d29806e498bfe89a3 100644 (file)
 
 #include <stdint.h>
 
-#include "native/jni.h"
-#include "native/native.h"
+#include "native/jni.hpp"
+#include "native/native.hpp"
 
 #if defined(ENABLE_JNI_HEADERS)
 # include "native/include/java_lang_Float.h"
 #endif
 
-#include "vm/builtin.h"
+#include "vm/vm.hpp"
+
+#include "vm/jit/builtin.hpp"
 
 
 // Native functions are exported as C functions.
@@ -77,16 +79,12 @@ static JNINativeMethod methods[] = {
  
 *******************************************************************************/
 
-// FIXME
-extern "C" { 
 void _Jv_java_lang_Float_init(void)
 {
-       utf *u;
-       u = utf_new_char("java/lang/Float");
+       utf* u = utf_new_char("java/lang/Float");
  
-       native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+       NativeMethods& nm = VM::get_current()->get_nativemethods();
+       nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
 }
 
 
index f65adb551f4264ae7fb93bc408f8533ea503535f..50f2c93360a9f192d921c3e617d85b3d452ec07a 100644 (file)
 
 #include "fdlibm/fdlibm.h"
 
-#include "native/jni.h"
-#include "native/native.h"
+#include "native/jni.hpp"
+#include "native/native.hpp"
 
 #if defined(ENABLE_JNI_HEADERS)
 # include "native/include/java_lang_Math.h"
 #endif
 
+#include "vm/vm.hpp"
+
 
 // Native functions are exported as C functions.
 extern "C" {
@@ -126,16 +128,12 @@ static JNINativeMethod methods[] = {
  
 *******************************************************************************/
 
-// FIXME
-extern "C" { 
 void _Jv_java_lang_Math_init(void)
 {
-       utf *u;
-       u = utf_new_char("java/lang/Math");
+       utf* u = utf_new_char("java/lang/Math");
  
-       native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+       NativeMethods& nm = VM::get_current()->get_nativemethods();
+       nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
 }
 
 
index 83d6df8668ab604154ab400ef6a21cf658e7d6ae..ac38a3751ed2a2cf2f4a2b5c34f97c354fb8f352 100644 (file)
 #include <stdint.h>
 #include <stdlib.h>
 
-#include "native/jni.h"
+#include "native/jni.hpp"
 #include "native/llni.h"
-#include "native/native.h"
+#include "native/native.hpp"
 
 #if defined(ENABLE_JNI_HEADERS)
 # include "native/include/java_lang_Object.h"
 #endif
 
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
 
 #include "vm/exceptions.hpp"
+#include "vm/javaobjects.hpp"
 
 
 // Native functions are exported as C functions.
@@ -51,16 +52,14 @@ extern "C" {
  */
 JNIEXPORT jclass JNICALL Java_java_lang_Object_getClass(JNIEnv *env, jobject obj)
 {
-       classinfo *c;
-
        if (obj == NULL) {
                exceptions_throw_nullpointerexception();
                return NULL;
        }
 
-       LLNI_class_get(obj, c);
+       java_lang_Object o(obj);
 
-       return (jclass) LLNI_classinfo_wrap(c);
+       return (jclass) LLNI_classinfo_wrap(o.get_Class());
 }
 
 
@@ -71,11 +70,9 @@ JNIEXPORT jclass JNICALL Java_java_lang_Object_getClass(JNIEnv *env, jobject obj
  */
 JNIEXPORT jint JNICALL Java_java_lang_Object_hashCode(JNIEnv *env, jobject _this)
 {
-#if defined(ENABLE_GC_CACAO)
-       assert(0);
-#else
-       return (int32_t) ((uintptr_t) _this);
-#endif
+       java_lang_Object o(_this);
+
+       return o.get_hashcode();
 }
 
 
@@ -148,16 +145,12 @@ static JNINativeMethod methods[] = {
  
 *******************************************************************************/
  
-// FIXME
-extern "C" {
 void _Jv_java_lang_Object_init(void)
 {
-       utf *u;
-       u = utf_new_char("java/lang/Object");
+       utf* u = utf_new_char("java/lang/Object");
  
-       native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+       NativeMethods& nm = VM::get_current()->get_nativemethods();
+       nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
 }
 
 
index fce3463edf4d663c9c017b1f8863a3b812e7e9be..a837bf2865c2c91e8e1c267388419c05755ad2a0 100644 (file)
@@ -29,8 +29,8 @@
 
 #include "mm/gc.hpp"
 
-#include "native/jni.h"
-#include "native/native.h"
+#include "native/jni.hpp"
+#include "native/native.hpp"
 
 #if defined(ENABLE_JNI_HEADERS)
 # include "native/include/java_lang_Runtime.h"
@@ -105,16 +105,12 @@ static JNINativeMethod methods[] = {
  
 *******************************************************************************/
  
-// FIXME
-extern "C" {
 void _Jv_java_lang_Runtime_init(void)
 {
-       utf *u;
-       u = utf_new_char("java/lang/Runtime");
-       native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+       utf* u = utf_new_char("java/lang/Runtime");
+
+       NativeMethods& nm = VM::get_current()->get_nativemethods();
+       nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
 }
 
 
index e0cb3517b9c26585f815a14ec6c70d53aadd998d..b86e539d45c22aa35cd12947f3c0ab84984a0633 100644 (file)
@@ -29,9 +29,9 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include "native/jni.h"
+#include "native/jni.hpp"
 #include "native/llni.h"
-#include "native/native.h"
+#include "native/native.hpp"
 
 #if defined(ENABLE_JNI_HEADERS)
 # include "native/include/java_lang_String.h"
@@ -198,16 +198,12 @@ static JNINativeMethod methods[] = {
  
 *******************************************************************************/
  
-// FIXME
-extern "C" {
 void _Jv_java_lang_String_init(void)
 {
-       utf *u;
-       u = utf_new_char("java/lang/String");
+       utf* u = utf_new_char("java/lang/String");
  
-       native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+       NativeMethods& nm = VM::get_current()->get_nativemethods();
+       nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
 }
 
 
index e334d9b38e0386c3e8aab9f994b7d6b85e6117fa..ccc1c0eccc57c92e9d751b0db67fa881eff5e5a0 100644 (file)
 
 #include "mm/memory.h"
 
-#include "native/jni.h"
-#include "native/native.h"
+#include "native/jni.hpp"
+#include "native/native.hpp"
 
 #if defined(ENABLE_JNI_HEADERS)
 # include "native/include/java_lang_System.h"
 #endif
 
-#include "vm/builtin.h"
-#include "vm/properties.h"
+#include "vm/jit/builtin.hpp"
+#include "vm/properties.hpp"
 #include "vm/string.hpp"
+#include "vm/vm.hpp"
 
 
 // Native functions are exported as C functions.
@@ -78,7 +79,7 @@ JNIEXPORT jstring JNICALL Java_java_lang_System_getProperty0(JNIEnv *env, jclass
 
        /* get the property from the internal table */
 
-       value = properties_get(key);
+       value = VM::get_current()->get_properties().get(key);
 
        /* release the memory allocated in javastring_tochar */
 
@@ -109,16 +110,12 @@ static JNINativeMethod methods[] = {
  
 *******************************************************************************/
  
-// FIXME
-extern "C" {
 void _Jv_java_lang_System_init(void)
 {
-       utf *u;
-       u = utf_new_char("java/lang/System");
+       utf* u = utf_new_char("java/lang/System");
  
-       native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+       NativeMethods& nm = VM::get_current()->get_nativemethods();
+       nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
 }
 
 
index 5ee1120313cb61a2192642e0d3e05494521bb943..99a7393a06f78562a9a4d75d263a9600a63560f7 100644 (file)
@@ -27,8 +27,8 @@
 
 #include <stdint.h>
 
-#include "native/jni.h"
-#include "native/native.h"
+#include "native/jni.hpp"
+#include "native/native.hpp"
 
 #if defined(ENABLE_JNI_HEADERS)
 # include "native/include/java_lang_Thread.h"
@@ -38,7 +38,7 @@
 
 #include "toolbox/logging.h"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/javaobjects.hpp"
 
 
@@ -199,16 +199,12 @@ static JNINativeMethod methods[] = {
  
 *******************************************************************************/
  
-// FIXME
-extern "C" {
 void _Jv_java_lang_Thread_init(void)
 {
-       utf *u;
-       u = utf_new_char("java/lang/Thread");
+       utf* u = utf_new_char("java/lang/Thread");
  
-       native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+       NativeMethods& nm = VM::get_current()->get_nativemethods();
+       nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
 }
 
 
index 10993c0610c9fa181805eda40e7faef2c279f0b4..f5d566ea574bf47e299a24065d99c7d2629b33aa 100644 (file)
@@ -28,9 +28,9 @@
 #include <assert.h>
 #include <stdint.h>
 
-#include "native/jni.h"
+#include "native/jni.hpp"
 #include "native/llni.h"
-#include "native/native.h"
+#include "native/native.hpp"
 
 #if defined(ENABLE_JNI_HEADERS)
 # include "native/include/java_lang_Throwable.h"
@@ -92,16 +92,12 @@ static JNINativeMethod methods[] = {
  
 *******************************************************************************/
  
-// FIXME
-extern "C" {
 void _Jv_java_lang_Throwable_init(void)
 {
-       utf *u;
-       u = utf_new_char("java/lang/Throwable");
+       utf* u = utf_new_char("java/lang/Throwable");
  
-       native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+       NativeMethods& nm = VM::get_current()->get_nativemethods();
+       nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
 }
 
 
index c592f30773618a11a665b5ef65b07b27339e5eda..b232ed826f09fc15bf31e652c46e511403264e41 100644 (file)
@@ -54,7 +54,7 @@ libnativevmcore_la_SOURCES = \
        java_lang_VMSystem.cpp \
        java_lang_VMThread.cpp \
        java_lang_VMThrowable.cpp \
-       java_lang_management_VMManagementFactory.c \
+       java_lang_management_VMManagementFactory.cpp \
        java_lang_reflect_VMConstructor.cpp \
        java_lang_reflect_VMField.cpp \
        java_lang_reflect_VMMethod.cpp \
index ee0646a78945da921d5661ca92732c454205c60e..3834360261ad7325c172ead60d39634baa29705a 100644 (file)
@@ -27,8 +27,8 @@
 
 #include <stdint.h>
 
-#include "native/jni.h"
-#include "native/native.h"
+#include "native/jni.hpp"
+#include "native/native.hpp"
 
 #if defined(ENABLE_JNI_HEADERS)
 # include "native/vm/include/gnu_classpath_VMStackWalker.h"
@@ -124,16 +124,12 @@ static JNINativeMethod methods[] = {
 
 *******************************************************************************/
 
-// FIXME
-extern "C" {
 void _Jv_gnu_classpath_VMStackWalker_init(void)
 {
-       utf *u;
-
-       u = utf_new_char("gnu/classpath/VMStackWalker");
+       utf* u = utf_new_char("gnu/classpath/VMStackWalker");
 
-       native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+       NativeMethods& nm = VM::get_current()->get_nativemethods();
+       nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
 }
 
 
index ebd09b0405add9fc83ff1e051b5bda6e41ac685f..0789c0eda8d96a7a61fb1c31e31e32ab9a86c337 100644 (file)
 
 #include "mm/memory.h"
 
-#include "native/jni.h"
-#include "native/native.h"
+#include "native/jni.hpp"
+#include "native/native.hpp"
 
 #if defined(ENABLE_JNI_HEADERS)
 # include "native/include/gnu_classpath_VMSystemProperties.h"
 #endif
 
 #include "vm/exceptions.hpp"
-#include "vm/properties.h"
+#include "vm/properties.hpp"
 #include "vm/vm.hpp"
 
 
@@ -63,9 +63,8 @@ JNIEXPORT void JNICALL Java_gnu_classpath_VMSystemProperties_preInit(JNIEnv *env
                return;
        }
 
-       /* fill the java.util.Properties object */
-
-       properties_system_add_all(p);
+       // Fill the java.util.Properties object.
+       VM::get_current()->get_properties().fill(p);
 }
 
 
@@ -96,9 +95,9 @@ JNIEXPORT void JNICALL Java_gnu_classpath_VMSystemProperties_postInit(JNIEnv *en
        /* XXX when we do it that way, we can't set these properties on
           commandline */
 
-       java_home = properties_get("java.home");
+       java_home = VM::get_current()->get_properties().get("java.home");
 
-       properties_system_add(p, "gnu.classpath.home", java_home);
+       Properties::put(p, "gnu.classpath.home", java_home);
 
        len =
                strlen("file://") +
@@ -112,7 +111,7 @@ JNIEXPORT void JNICALL Java_gnu_classpath_VMSystemProperties_postInit(JNIEnv *en
        strcat(path, java_home);
        strcat(path, "/lib");
 
-       properties_system_add(p, "gnu.classpath.home.url", path);
+       Properties::put(p, "gnu.classpath.home.url", path);
 
        MFREE(path, char, len);
 #endif
@@ -135,16 +134,12 @@ static JNINativeMethod methods[] = {
 
 *******************************************************************************/
 
-// FIXME
-extern "C" {
 void _Jv_gnu_classpath_VMSystemProperties_init(void)
 {
-       utf *u;
+       utf* u = utf_new_char("gnu/classpath/VMSystemProperties");
 
-       u = utf_new_char("gnu/classpath/VMSystemProperties");
-
-       native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+       NativeMethods& nm = VM::get_current()->get_nativemethods();
+       nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
 }
 
 
index e647e4d940e81a9a47d05b95fcde3f0701693496..9276ebb8feebcbf5fec468178da435e9fc36cf48 100644 (file)
@@ -27,7 +27,7 @@
 
 #include <stdint.h>
 
-#include "native/jni.h"
+#include "native/jni.hpp"
 
 #include "native/include/java_lang_Object.h"
 #include "native/include/gnu_classpath_jdwp_VMFrame.h"
index 54ff53478a647926d4dce1029cc3a94d181551c8..dec60350128f393c74ed6dd420b681ff6c6179b2 100644 (file)
@@ -27,7 +27,7 @@
 
 #include <stdint.h>
 
-#include "native/jni.h"
+#include "native/jni.hpp"
 
 #include "native/include/gnu_classpath_jdwp_VMMethod.h"
 
index 9e06a6b57b737eb72827bb27444d8296e3118aa1..eaf47e6301c3cfea38b5233c8360fbd5f19c5cb4 100644 (file)
@@ -29,7 +29,7 @@
 #include <string.h>
 
 #include "toolbox/logging.h"
-#include "native/jni.h"
+#include "native/jni.hpp"
 #include "native/include/java_lang_Thread.h"
 #include "native/include/java_nio_ByteBuffer.h"
 #include "native/include/java_lang_Class.h"
index 1d4b014ac507970bb46bae7736c460491a1910c9..c0b34194224d2ec9d1ca69d1f0cc0a39e054b6fc 100644 (file)
 
 #include <stdint.h>
 
-#include "native/jni.h"
+#include "native/jni.hpp"
 #include "native/llni.h"
-#include "native/native.h"
+#include "native/native.hpp"
 
 #if defined(ENABLE_JNI_HEADERS)
 # include "native/vm/include/gnu_java_lang_VMCPStringBuilder.h"
 #endif
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/exceptions.hpp"
 #include "vm/globals.hpp"
 #include "vm/javaobjects.hpp"
@@ -101,16 +101,12 @@ static JNINativeMethod methods[] = {
 
 *******************************************************************************/
 
-// FIXME
-extern "C" {
 void _Jv_gnu_java_lang_VMCPStringBuilder_init(void)
 {
-       utf *u;
+       utf* u = utf_new_char("gnu/java/lang/VMCPStringBuilder");
 
-       u = utf_new_char("gnu/java/lang/VMCPStringBuilder");
-
-       native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+       NativeMethods& nm = VM::get_current()->get_nativemethods();
+       nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
 }
 
 
index a6b0f3a117988293e5843ea81b6560930bcb5304..069b7dffe4c0882dbc3f562f0cf4afdb58171788 100644 (file)
@@ -29,8 +29,8 @@
 
 #include "mm/gc.hpp"
 
-#include "native/jni.h"
-#include "native/native.h"
+#include "native/jni.hpp"
+#include "native/native.hpp"
 
 #if defined(ENABLE_JNI_HEADERS)
 # include "native/vm/include/gnu_java_lang_management_VMClassLoadingMXBeanImpl.h"
@@ -84,6 +84,7 @@ JNIEXPORT jboolean JNICALL Java_gnu_java_lang_management_VMClassLoadingMXBeanImp
 /*     return _Jv_jvm->Java_gnu_java_lang_management_VMClassLoadingMXBeanImpl_verbose; */
 #warning Move to C++
        log_println("Java_gnu_java_lang_management_VMClassLoadingMXBeanImpl_isVerbose: MOVE TO C++!");
+       return 0;
 }
 
 
@@ -118,16 +119,12 @@ static JNINativeMethod methods[] = {
 
 *******************************************************************************/
 
-// FIXME
-extern "C" {
 void _Jv_gnu_java_lang_management_VMClassLoadingMXBeanImpl_init(void)
 {
-       utf *u;
+       utf* u = utf_new_char("gnu/java/lang/management/VMClassLoadingMXBeanImpl");
 
-       u = utf_new_char("gnu/java/lang/management/VMClassLoadingMXBeanImpl");
-
-       native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+       NativeMethods& nm = VM::get_current()->get_nativemethods();
+       nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
 }
 
 
index a48af390eb6909c6292779b056682313e50ca287..6ad098df7966b09fb737457aed0aef86a9f787e8 100644 (file)
 
 #include "mm/gc.hpp"
 
-#include "native/jni.h"
-#include "native/native.h"
+#include "native/jni.hpp"
+#include "native/native.hpp"
 
 #if defined(ENABLE_JNI_HEADERS)
 # include "native/vm/include/gnu_java_lang_management_VMMemoryMXBeanImpl.h"
 #endif
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/class.h"
 #include "vm/global.h"
-#include "vm/loader.h"               /* XXX only for load_class_bootstrap */
+#include "vm/loader.hpp"               /* XXX only for load_class_bootstrap */
 #include "vm/options.h"
 #include "vm/vm.hpp"
 
@@ -173,16 +173,12 @@ static JNINativeMethod methods[] = {
 
 *******************************************************************************/
 
-// FIXME
-extern "C" {
 void _Jv_gnu_java_lang_management_VMMemoryMXBeanImpl_init(void)
 {
-       utf *u;
-
-       u = utf_new_char("gnu/java/lang/management/VMMemoryMXBeanImpl");
+       utf* u = utf_new_char("gnu/java/lang/management/VMMemoryMXBeanImpl");
 
-       native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+       NativeMethods& nm = VM::get_current()->get_nativemethods();
+       nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
 }
 
 
index 2b9e3c4e5b20829e56c009d74212e72910942a68..c17382a54fc729faca297936393680a2bd4f5e11 100644 (file)
 
 #include <stdint.h>
 
-#include "native/jni.h"
-#include "native/native.h"
+#include "native/jni.hpp"
+#include "native/native.hpp"
 
 #if defined(ENABLE_JNI_HEADERS)
 # include "native/vm/include/gnu_java_lang_management_VMRuntimeMXBeanImpl.h"
 #endif
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/global.h"
 #include "vm/globals.hpp"
 #include "vm/utf8.h"
@@ -64,7 +64,7 @@ JNIEXPORT java_handle_objectarray_t* JNICALL Java_gnu_java_lang_management_VMRun
  */
 JNIEXPORT int64_t JNICALL Java_gnu_java_lang_management_VMRuntimeMXBeanImpl_getStartTime(JNIEnv *env, jclass clazz)
 {
-       return vm->get_starttime();
+       return VM::get_current()->get_starttime();
 }
 
 } // extern "C"
@@ -84,16 +84,12 @@ static JNINativeMethod methods[] = {
 
 *******************************************************************************/
 
-// FIXME
-extern "C" {
 void _Jv_gnu_java_lang_management_VMRuntimeMXBeanImpl_init(void)
 {
-       utf *u;
-
-       u = utf_new_char("gnu/java/lang/management/VMRuntimeMXBeanImpl");
+       utf* u = utf_new_char("gnu/java/lang/management/VMRuntimeMXBeanImpl");
 
-       native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+       NativeMethods& nm = VM::get_current()->get_nativemethods();
+       nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
 }
 
 
index e8f3916cbf8821a491b94bd55c80e60724b87cce..0ad83bcde2b47390b6d148c00a0008c671e1d7b2 100644 (file)
@@ -29,8 +29,8 @@
 
 #include "mm/gc.hpp"
 
-#include "native/jni.h"
-#include "native/native.h"
+#include "native/jni.hpp"
+#include "native/native.hpp"
 
 #if defined(ENABLE_JNI_HEADERS)
 # include "native/vm/include/gnu_java_lang_management_VMThreadMXBeanImpl.h"
@@ -189,16 +189,12 @@ static JNINativeMethod methods[] = {
 
 *******************************************************************************/
 
-// FIXME
-extern "C" {
 void _Jv_gnu_java_lang_management_VMThreadMXBeanImpl_init(void)
 {
-       utf *u;
-
-       u = utf_new_char("gnu/java/lang/management/VMThreadMXBeanImpl");
+       utf* u = utf_new_char("gnu/java/lang/management/VMThreadMXBeanImpl");
 
-       native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+       NativeMethods& nm = VM::get_current()->get_nativemethods();
+       nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
 }
 
 
index 70568657fa86ce424324acdc7a51cb0ae0382a75..5e2136aa53ab47da8d4ffc0ab6459128f3f34556 100644 (file)
@@ -27,9 +27,9 @@
 
 #include <stdint.h>
 
-#include "native/jni.h"
+#include "native/jni.hpp"
 #include "native/llni.h"
-#include "native/native.h"
+#include "native/native.hpp"
 
 #if defined(ENABLE_JNI_HEADERS)
 # include "native/vm/include/java_lang_VMClass.h"
@@ -615,16 +615,12 @@ static JNINativeMethod methods[] = {
 
 *******************************************************************************/
 
-// FIXME
-extern "C" {
 void _Jv_java_lang_VMClass_init(void)
 {
-       utf *u;
-
-       u = utf_new_char("java/lang/VMClass");
+       utf* u = utf_new_char("java/lang/VMClass");
 
-       native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+       NativeMethods& nm = VM::get_current()->get_nativemethods();
+       nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
 }
 
 
index 6acc53b5f3641dfff76cbc6f2043de54688d54cd..926d825f8c16e117562e5d4b38ab60fbb6e3bed0 100644 (file)
 
 #include "mm/memory.h"
 
-#include "native/jni.h"
+#include "native/jni.hpp"
 #include "native/llni.h"
-#include "native/native.h"
+#include "native/native.hpp"
 
 #if defined(ENABLE_JNI_HEADERS)
 # include "native/vm/include/java_lang_VMClassLoader.h"
 #endif
 
 #include "toolbox/logging.h"
-#include "toolbox/list.h"
+#include "toolbox/list.hpp"
 
 #if defined(ENABLE_ASSERTION)
-#include "vm/assertion.h"
+#include "vm/assertion.hpp"
 #endif
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/class.h"
 #include "vm/classcache.h"
 #include "vm/exceptions.hpp"
 #include "vm/initialize.h"
 #include "vm/javaobjects.hpp"
 #include "vm/linker.h"
-#include "vm/loader.h"
+#include "vm/loader.hpp"
 #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"
 
@@ -249,7 +248,6 @@ JNIEXPORT jobject JNICALL Java_java_lang_VMClassLoader_nativeGetResources(JNIEnv
        java_handle_t        *o;         /* vector being created     */
        methodinfo           *m;         /* "add" method of vector   */
        java_handle_t        *path;      /* path to be added         */
-       list_classpath_entry *lce;       /* classpath entry          */
        utf                  *utfname;   /* utf to look for          */
        char                 *buffer;    /* char buffer              */
        char                 *namestart; /* start of name to use     */
@@ -320,8 +318,9 @@ JNIEXPORT jobject JNICALL Java_java_lang_VMClassLoader_nativeGetResources(JNIEnv
 
        /* iterate over all classpath entries */
 
-       for (lce = (list_classpath_entry*) list_first(list_classpath_entries); lce != NULL;
-                lce = (list_classpath_entry*) list_next(list_classpath_entries, lce)) {
+       for (List<list_classpath_entry*>::iterator it = list_classpath_entries->begin(); it != list_classpath_entries->end(); it++) {
+               list_classpath_entry* lce = *it;
+
                /* clear path pointer */
                path = NULL;
 
@@ -422,7 +421,6 @@ JNIEXPORT jobject JNICALL Java_java_lang_VMClassLoader_packageAssertionStatus0(J
 #if defined(ENABLE_ASSERTION)
        java_handle_t     *js;
        methodinfo        *m;
-       assertion_name_t  *item;
 #endif
 
        /* new HashMap() */
@@ -451,13 +449,11 @@ JNIEXPORT jobject JNICALL Java_java_lang_VMClassLoader_packageAssertionStatus0(J
                return NULL;
        }
 
-       item = (assertion_name_t *)list_first(list_assertion_names);
+       for (List<assertion_name_t*>::iterator it = list_assertion_names->begin(); it != list_assertion_names->end(); it++) {
+               assertion_name_t* item = *it;
 
-       while (item != NULL) {
-               if (item->package == false) {
-                       item = (assertion_name_t *)list_next(list_assertion_names, item);
+               if (item->package == false)
                        continue;
-               }
                
                if (strcmp(item->name, "") == 0) {
                        /* unnamed package wanted */
@@ -476,8 +472,6 @@ JNIEXPORT jobject JNICALL Java_java_lang_VMClassLoader_packageAssertionStatus0(J
                else {
                        vm_call_method(m, hm, js, jfalse);
                }
-
-               item = (assertion_name_t *)list_next(list_assertion_names, item);
        }
 #endif
 
@@ -495,7 +489,6 @@ JNIEXPORT jobject JNICALL Java_java_lang_VMClassLoader_classAssertionStatus0(JNI
 #if defined(ENABLE_ASSERTION)
        java_handle_t     *js;
        methodinfo        *m;
-       assertion_name_t  *item;
 #endif
 
        /* new HashMap() */
@@ -524,13 +517,11 @@ JNIEXPORT jobject JNICALL Java_java_lang_VMClassLoader_classAssertionStatus0(JNI
                return NULL;
        }
 
-       item = (assertion_name_t *)list_first(list_assertion_names);
+       for (List<assertion_name_t*>::iterator it = list_assertion_names->begin(); it != list_assertion_names->end(); it++) {
+               assertion_name_t* item = *it;
 
-       while (item != NULL) {
-               if (item->package == true) {
-                       item = (assertion_name_t *)list_next(list_assertion_names, item);
+               if (item->package == true)
                        continue;
-               }
 
                js = javastring_new_from_ascii(item->name);
                if (js == NULL) {
@@ -543,8 +534,6 @@ JNIEXPORT jobject JNICALL Java_java_lang_VMClassLoader_classAssertionStatus0(JNI
                else {
                        vm_call_method(m, hm, js, jfalse);
                }
-
-               item = (assertion_name_t *)list_next(list_assertion_names, item);
        }
 #endif
 
@@ -608,16 +597,12 @@ static JNINativeMethod methods[] = {
 
 *******************************************************************************/
 
-// FIXME
-extern "C" {
 void _Jv_java_lang_VMClassLoader_init(void)
 {
-       utf *u;
+       utf* u = utf_new_char("java/lang/VMClassLoader");
 
-       u = utf_new_char("java/lang/VMClassLoader");
-
-       native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+       NativeMethods& nm = VM::get_current()->get_nativemethods();
+       nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
 }
 
 
index 5b63de218bf63aaa2c61dcf7a19b1dc695a571ff..769d1a071f9390dd00bc4aec1c55734bc54db02d 100644 (file)
 
 #include <stdint.h>
 
-#include "native/jni.h"
+#include "native/jni.hpp"
 #include "native/llni.h"
-#include "native/native.h"
+#include "native/native.hpp"
 
 #if defined(ENABLE_JNI_HEADERS)
 # include "native/vm/include/java_lang_VMObject.h"
 #endif
 
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/exceptions.hpp"
+#include "vm/javaobjects.hpp"
 #include "vm/utf8.h"
 
 
@@ -50,18 +51,16 @@ extern "C" {
  * Method:    getClass
  * Signature: (Ljava/lang/Object;)Ljava/lang/Class;
  */
-JNIEXPORT jclass JNICALL Java_java_lang_VMObject_getClass(JNIEnv *env, jclass clazz, jobject obj)
+JNIEXPORT jclass JNICALL Java_java_lang_VMObject_getClass(JNIEnvenv, jclass clazz, jobject obj)
 {
-       classinfo *c;
-
        if (obj == NULL) {
                exceptions_throw_nullpointerexception();
                return NULL;
        }
 
-       LLNI_class_get(obj, c);
+       java_lang_Object o(obj);
 
-       return (jclass) LLNI_classinfo_wrap(c);
+       return (jclass) LLNI_classinfo_wrap(o.get_Class());
 }
 
 
@@ -70,16 +69,9 @@ JNIEXPORT jclass JNICALL Java_java_lang_VMObject_getClass(JNIEnv *env, jclass cl
  * Method:    clone
  * Signature: (Ljava/lang/Cloneable;)Ljava/lang/Object;
  */
-JNIEXPORT jobject JNICALL Java_java_lang_VMObject_clone(JNIEnv *env, jclass clazz, jobject _this)
+JNIEXPORT jobject JNICALL Java_java_lang_VMObject_clone(JNIEnvenv, jclass clazz, jobject _this)
 {
-       java_handle_t *o;
-       java_handle_t *co;
-
-       o = (java_handle_t *) _this;
-
-       co = builtin_clone(NULL, o);
-
-       return (jobject) co;
+       return builtin_clone(NULL, _this);
 }
 
 
@@ -88,10 +80,10 @@ JNIEXPORT jobject JNICALL Java_java_lang_VMObject_clone(JNIEnv *env, jclass claz
  * Method:    notify
  * Signature: (Ljava/lang/Object;)V
  */
-JNIEXPORT void JNICALL Java_java_lang_VMObject_notify(JNIEnv *env, jclass clazz, jobject _this)
+JNIEXPORT void JNICALL Java_java_lang_VMObject_notify(JNIEnvenv, jclass clazz, jobject _this)
 {
 #if defined(ENABLE_THREADS)
-       lock_notify_object((java_handle_t *) _this);
+       lock_notify_object(_this);
 #endif
 }
 
@@ -101,10 +93,10 @@ JNIEXPORT void JNICALL Java_java_lang_VMObject_notify(JNIEnv *env, jclass clazz,
  * Method:    notifyAll
  * Signature: (Ljava/lang/Object;)V
  */
-JNIEXPORT void JNICALL Java_java_lang_VMObject_notifyAll(JNIEnv *env, jclass clazz, jobject _this)
+JNIEXPORT void JNICALL Java_java_lang_VMObject_notifyAll(JNIEnvenv, jclass clazz, jobject _this)
 {
 #if defined(ENABLE_THREADS)
-       lock_notify_all_object((java_handle_t *) _this);
+       lock_notify_all_object(_this);
 #endif
 }
 
@@ -114,7 +106,7 @@ JNIEXPORT void JNICALL Java_java_lang_VMObject_notifyAll(JNIEnv *env, jclass cla
  * Method:    wait
  * Signature: (Ljava/lang/Object;JI)V
  */
-JNIEXPORT void JNICALL Java_java_lang_VMObject_wait(JNIEnv *env, jclass clazz, jobject o, jlong ms, jint ns)
+JNIEXPORT void JNICALL Java_java_lang_VMObject_wait(JNIEnvenv, jclass clazz, jobject o, jlong ms, jint ns)
 {
 #if defined(ENABLE_JVMTI)
        /* Monitor Wait */
@@ -122,7 +114,7 @@ JNIEXPORT void JNICALL Java_java_lang_VMObject_wait(JNIEnv *env, jclass clazz, j
 #endif
 
 #if defined(ENABLE_THREADS)
-       lock_wait_for_object((java_handle_t *) o, ms, ns);
+       lock_wait_for_object(o, ms, ns);
 #endif
 
 #if defined(ENABLE_JVMTI)
@@ -152,16 +144,12 @@ static JNINativeMethod methods[] = {
 
 *******************************************************************************/
 
-// FIXME
-extern "C" {
 void _Jv_java_lang_VMObject_init(void)
 {
-       utf *u;
-
-       u = utf_new_char("java/lang/VMObject");
+       utf* u = utf_new_char("java/lang/VMObject");
 
-       native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+       NativeMethods& nm = VM::get_current()->get_nativemethods();
+       nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
 }
 
 
index 84f13d553f762441f6879afd7f3c2a67e4deb180..93b8833f1335bd0aa0ec2609993f643b27353790 100644 (file)
 # include <mach/mach.h>
 #endif
 
-#include "mm/dumpmemory.h"
+#include "mm/memory.h"
 #include "mm/gc.hpp"
 
-#include "native/jni.h"
-#include "native/native.h"
+#include "native/jni.hpp"
+#include "native/native.hpp"
 
 #if defined(ENABLE_JNI_HEADERS)
 # include "native/vm/include/java_lang_VMRuntime.h"
 #endif
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/exceptions.hpp"
 #include "vm/os.hpp"
 #include "vm/string.hpp"
@@ -203,10 +203,7 @@ JNIEXPORT jint JNICALL Java_java_lang_VMRuntime_availableProcessors(JNIEnv *env,
  */
 JNIEXPORT jint JNICALL Java_java_lang_VMRuntime_nativeLoad(JNIEnv *env, jclass clazz, jstring libname, jobject loader)
 {
-       classloader_t *cl;
-       utf           *name;
-
-       cl = loader_hashtable_classloader_add((java_handle_t *) loader);
+       classloader_t* cl = loader_hashtable_classloader_add((java_handle_t *) loader);
 
        /* REMOVEME When we use Java-strings internally. */
 
@@ -215,9 +212,10 @@ JNIEXPORT jint JNICALL Java_java_lang_VMRuntime_nativeLoad(JNIEnv *env, jclass c
                return 0;
        }
 
-       name = javastring_toutf((java_handle_t *) libname, false);
+       utf* name = javastring_toutf((java_handle_t *) libname, false);
 
-       return native_library_load(env, name, cl);
+       NativeLibrary library(name, cl);
+       return library.load(env);
 }
 
 
@@ -232,7 +230,6 @@ JNIEXPORT jstring JNICALL Java_java_lang_VMRuntime_mapLibraryName(JNIEnv *env, j
        char          *buffer;
        int32_t        buffer_len;
        java_handle_t *o;
-       int32_t        dumpmarker;
 
        if (libname == NULL) {
                exceptions_throw_nullpointerexception();
@@ -249,9 +246,7 @@ JNIEXPORT jstring JNICALL Java_java_lang_VMRuntime_mapLibraryName(JNIEnv *env, j
                strlen(NATIVE_LIBRARY_SUFFIX) +
                strlen("0");
 
-       DMARKER;
-
-       buffer = DMNEW(char, buffer_len);
+       buffer = MNEW(char, buffer_len);
 
        /* generate library name */
 
@@ -263,7 +258,7 @@ JNIEXPORT jstring JNICALL Java_java_lang_VMRuntime_mapLibraryName(JNIEnv *env, j
 
        /* release memory */
 
-       DRELEASE;
+       MFREE(buffer, char, buffer_len);
 
        return (jstring) o;
 }
@@ -296,16 +291,12 @@ static JNINativeMethod methods[] = {
 
 *******************************************************************************/
 
-// FIXME
-extern "C" {
 void _Jv_java_lang_VMRuntime_init(void)
 {
-       utf *u;
+       utf* u = utf_new_char("java/lang/VMRuntime");
 
-       u = utf_new_char("java/lang/VMRuntime");
-
-       native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+       NativeMethods& nm = VM::get_current()->get_nativemethods();
+       nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
 }
 
 
index 632c429b8fd9ed8ff957a90c5d26788bd3996398..9579db252c8271851742b547540a6170ccf5cd2c 100644 (file)
 #include <stdint.h>
 #include <stdlib.h>
 
-#include "native/jni.h"
-#include "native/native.h"
+#include "native/jni.hpp"
+#include "native/native.hpp"
 
 #if defined(ENABLE_JNI_HEADERS)
 # include "native/vm/include/java_lang_VMString.h"
 #endif
 
 #include "vm/string.hpp"
+#include "vm/vm.hpp"
 
 
 // Native functions are exported as C functions.
@@ -70,16 +71,12 @@ static JNINativeMethod methods[] = {
 
 *******************************************************************************/
 
-// FIXME
-extern "C" {
 void _Jv_java_lang_VMString_init(void)
 {
-       utf *u;
-
-       u = utf_new_char("java/lang/VMString");
+       utf* u = utf_new_char("java/lang/VMString");
 
-       native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+       NativeMethods& nm = VM::get_current()->get_nativemethods();
+       nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
 }
 
 
index fcdc273ae1112b57577bc897487427393943cbe2..e5b3e95303fc5b2fc78ab54a5d7225fdf0adf8a7 100644 (file)
 
 #include "mm/gc.hpp"
 
-#include "native/jni.h"
+#include "native/jni.hpp"
 #include "native/llni.h"
-#include "native/native.h"
+#include "native/native.hpp"
 
 #if defined(ENABLE_JNI_HEADERS)
 # include "native/vminclude/java_lang_VMSystem.h"
 #endif
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
+#include "vm/javaobjects.hpp"
 
 
 // Native functions are exported as C functions.
@@ -61,18 +62,11 @@ JNIEXPORT void JNICALL Java_java_lang_VMSystem_arraycopy(JNIEnv *env, jclass cla
  * Method:    identityHashCode
  * Signature: (Ljava/lang/Object;)I
  */
-JNIEXPORT jint JNICALL Java_java_lang_VMSystem_identityHashCode(JNIEnv *env, jclass clazz, jobject o)
+JNIEXPORT jint JNICALL Java_java_lang_VMSystem_identityHashCode(JNIEnv *env, jclass clazz, jobject obj)
 {
-       int32_t hashcode;
+       java_lang_Object o(obj);
 
-       // XXX This critical section should be inside the heap function.
-       LLNI_CRITICAL_START;
-
-       hashcode = heap_hashcode(LLNI_UNWRAP((java_handle_t *) o));
-
-       LLNI_CRITICAL_END;
-
-       return hashcode;
+       return o.get_hashcode();
 }
 
 } // extern "C"
@@ -92,16 +86,12 @@ static JNINativeMethod methods[] = {
 
 *******************************************************************************/
 
-// FIXME
-extern "C" {
 void _Jv_java_lang_VMSystem_init(void)
 {
-       utf *u;
-
-       u = utf_new_char("java/lang/VMSystem");
+       utf* u = utf_new_char("java/lang/VMSystem");
 
-       native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+       NativeMethods& nm = VM::get_current()->get_nativemethods();
+       nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
 }
 
 
index dde8384ebf7725826aabb6401e42bd1c331de0a2..da3eccb25488ba8f6f45dc8d81798a7ac3184940 100644 (file)
 
 #include <stdint.h>
 
-#include "native/jni.h"
+#include "native/jni.hpp"
 #include "native/llni.h"
-#include "native/native.h"
+#include "native/native.hpp"
 
 #if defined(ENABLE_JNI_HEADERS)
 # include "native/vm/include/java_lang_VMThread.h"
 #endif
 
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
 #include "threads/thread.hpp"
 
 #include "vm/exceptions.hpp"
@@ -346,16 +346,12 @@ static JNINativeMethod methods[] = {
 
 *******************************************************************************/
 
-// FIXME
-extern "C" {
 void _Jv_java_lang_VMThread_init(void)
 {
-       utf *u;
-
-       u = utf_new_char("java/lang/VMThread");
+       utf* u = utf_new_char("java/lang/VMThread");
 
-       native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+       NativeMethods& nm = VM::get_current()->get_nativemethods();
+       nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
 }
 
 
index 64247cdc1fdfb49cc91ad531cca71209d61f3a3e..d62fe2926d48200e96df73bfec11f287184ebfc6 100644 (file)
 
 #include "vm/types.h"
 
-#include "native/jni.h"
+#include "native/jni.hpp"
 #include "native/llni.h"
-#include "native/native.h"
+#include "native/native.hpp"
 
 #if defined(ENABLE_JNI_HEADERS)
 # include "native/vm/include/java_lang_VMThrowable.h"
 #endif
 
-#include "vm/array.h"
-#include "vm/builtin.h"
+#include "vm/array.hpp"
+#include "vm/jit/builtin.hpp"
 #include "vm/exceptions.hpp"
 #include "vm/globals.hpp"
 #include "vm/javaobjects.hpp"
-#include "vm/loader.h"
+#include "vm/loader.hpp"
 #include "vm/string.hpp"
 
-#include "vm/jit/code.h"
-#include "vm/jit/linenumbertable.h"
+#include "vm/jit/code.hpp"
+#include "vm/jit/linenumbertable.hpp"
 #include "vm/jit/stacktrace.hpp"
 
 
@@ -137,11 +137,10 @@ JNIEXPORT jobjectArray JNICALL Java_java_lang_VMThrowable_getStackTrace(JNIEnv *
                        linenumber = -1;
                }
                else {
-                       /* FIXME The linenumbertable_linenumber_for_pc could
-                          change the methodinfo pointer when hitting an inlined
-                          method. */
+                       /* FIXME linenumbertable->find could change the methodinfo
+                          pointer when hitting an inlined method. */
 
-                       linenumber = linenumbertable_linenumber_for_pc(&m, code, ste->pc);
+                       linenumber = code->linenumbertable->find(&m, ste->pc);
                        linenumber = (linenumber == 0) ? -1 : linenumber;
                }
 
@@ -181,15 +180,12 @@ static JNINativeMethod methods[] = {
 
 *******************************************************************************/
 
-extern "C" {
 void _Jv_java_lang_VMThrowable_init(void)
 {
-       utf *u;
-
-       u = utf_new_char("java/lang/VMThrowable");
+       utf* u = utf_new_char("java/lang/VMThrowable");
 
-       native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+       NativeMethods& nm = VM::get_current()->get_nativemethods();
+       nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
 }
 
 
diff --git a/src/native/vm/gnuclasspath/java_lang_management_VMManagementFactory.c b/src/native/vm/gnuclasspath/java_lang_management_VMManagementFactory.c
deleted file mode 100644 (file)
index 8d1130a..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-/* src/native/vm/gnuclasspath/java_lang_management_VMManagementFactory.c
-
-   Copyright (C) 1996-2005, 2006, 2007, 2008
-   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
-
-   This file is part of CACAO.
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2, or (at
-   your option) any later version.
-
-   This program is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-   02110-1301, USA.
-
-*/
-
-
-#include "config.h"
-
-#include <stdlib.h>
-
-#include "vm/types.h"
-
-#include "native/jni.h"
-#include "native/native.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 "vm/globals.hpp"
-
-
-/*
- * Class:     java/lang/management/VMManagementFactory
- * Method:    getMemoryPoolNames
- * Signature: ()[Ljava/lang/String;
- */
-JNIEXPORT jobjectArray JNICALL Java_java_lang_management_VMManagementFactory_getMemoryPoolNames(JNIEnv *env, jclass clazz)
-{
-       java_handle_objectarray_t *oa;
-
-       log_println("Java_java_lang_management_VMManagementFactory_getMemoryPoolNames: IMPLEMENT ME!");
-
-       oa = builtin_anewarray(0, class_java_lang_String);
-
-       return oa;
-}
-
-
-/*
- * Class:     java/lang/management/VMManagementFactory
- * Method:    getMemoryManagerNames
- * Signature: ()[Ljava/lang/String;
- */
-JNIEXPORT jobjectArray JNICALL Java_java_lang_management_VMManagementFactory_getMemoryManagerNames(JNIEnv *env, jclass clazz)
-{
-       java_handle_objectarray_t *oa;
-
-       log_println("Java_java_lang_management_VMManagementFactory_getMemoryManagerNames: IMPLEMENT ME!");
-
-       oa = builtin_anewarray(0, class_java_lang_String);
-
-       return oa;
-}
-
-
-/*
- * Class:     java/lang/management/VMManagementFactory
- * Method:    getGarbageCollectorNames
- * Signature: ()[Ljava/lang/String;
- */
-JNIEXPORT jobjectArray JNICALL Java_java_lang_management_VMManagementFactory_getGarbageCollectorNames(JNIEnv *env, jclass clazz)
-{
-       java_handle_objectarray_t *oa;
-
-       log_println("Java_java_lang_management_VMManagementFactory_getGarbageCollectorNames: IMPLEMENT ME!");
-
-       oa = builtin_anewarray(0, class_java_lang_String);
-
-       return oa;
-}
-
-
-/* native methods implemented by this file ************************************/
-
-static JNINativeMethod methods[] = {
-       { "getMemoryPoolNames",       "()[Ljava/lang/String;", (void*) (uintptr_t) &Java_java_lang_management_VMManagementFactory_getMemoryPoolNames       },
-       { "getMemoryManagerNames",    "()[Ljava/lang/String;", (void*) (uintptr_t) &Java_java_lang_management_VMManagementFactory_getMemoryManagerNames    },
-       { "getGarbageCollectorNames", "()[Ljava/lang/String;", (void*) (uintptr_t) &Java_java_lang_management_VMManagementFactory_getGarbageCollectorNames },
-};
-
-
-/* _Jv_java_lang_management_VMManagementFactory_init ***************************
-
-   Register native functions.
-
-*******************************************************************************/
-
-void _Jv_java_lang_management_VMManagementFactory_init(void)
-{
-       utf *u;
-
-       u = utf_new_char("java/lang/management/VMManagementFactory");
-
-       native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
diff --git a/src/native/vm/gnuclasspath/java_lang_management_VMManagementFactory.cpp b/src/native/vm/gnuclasspath/java_lang_management_VMManagementFactory.cpp
new file mode 100644 (file)
index 0000000..10f450d
--- /dev/null
@@ -0,0 +1,139 @@
+/* src/native/vm/gnuclasspath/java_lang_management_VMManagementFactory.cpp
+
+   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 "vm/types.h"
+
+#include "native/jni.hpp"
+#include "native/native.hpp"
+
+#if defined(ENABLE_JNI_HEADERS)
+# include "native/vm/include/java_lang_management_VMManagementFactory.h"
+#endif
+
+#include "toolbox/logging.h"
+
+#include "vm/globals.hpp"
+#include "vm/vm.hpp"
+
+#include "vm/jit/builtin.hpp"
+
+
+// Native functions are exported as C functions.
+extern "C" {
+
+/*
+ * Class:     java/lang/management/VMManagementFactory
+ * Method:    getMemoryPoolNames
+ * Signature: ()[Ljava/lang/String;
+ */
+JNIEXPORT jobjectArray JNICALL Java_java_lang_management_VMManagementFactory_getMemoryPoolNames(JNIEnv *env, jclass clazz)
+{
+       java_handle_objectarray_t *oa;
+
+       log_println("Java_java_lang_management_VMManagementFactory_getMemoryPoolNames: IMPLEMENT ME!");
+
+       oa = builtin_anewarray(0, class_java_lang_String);
+
+       return oa;
+}
+
+
+/*
+ * Class:     java/lang/management/VMManagementFactory
+ * Method:    getMemoryManagerNames
+ * Signature: ()[Ljava/lang/String;
+ */
+JNIEXPORT jobjectArray JNICALL Java_java_lang_management_VMManagementFactory_getMemoryManagerNames(JNIEnv *env, jclass clazz)
+{
+       java_handle_objectarray_t *oa;
+
+       log_println("Java_java_lang_management_VMManagementFactory_getMemoryManagerNames: IMPLEMENT ME!");
+
+       oa = builtin_anewarray(0, class_java_lang_String);
+
+       return oa;
+}
+
+
+/*
+ * Class:     java/lang/management/VMManagementFactory
+ * Method:    getGarbageCollectorNames
+ * Signature: ()[Ljava/lang/String;
+ */
+JNIEXPORT jobjectArray JNICALL Java_java_lang_management_VMManagementFactory_getGarbageCollectorNames(JNIEnv *env, jclass clazz)
+{
+       java_handle_objectarray_t *oa;
+
+       log_println("Java_java_lang_management_VMManagementFactory_getGarbageCollectorNames: IMPLEMENT ME!");
+
+       oa = builtin_anewarray(0, class_java_lang_String);
+
+       return oa;
+}
+
+} // extern "C"
+
+
+/* native methods implemented by this file ************************************/
+
+static JNINativeMethod methods[] = {
+       { (char*) "getMemoryPoolNames",       (char*) "()[Ljava/lang/String;", (void*) (uintptr_t) &Java_java_lang_management_VMManagementFactory_getMemoryPoolNames       },
+       { (char*) "getMemoryManagerNames",    (char*) "()[Ljava/lang/String;", (void*) (uintptr_t) &Java_java_lang_management_VMManagementFactory_getMemoryManagerNames    },
+       { (char*) "getGarbageCollectorNames", (char*) "()[Ljava/lang/String;", (void*) (uintptr_t) &Java_java_lang_management_VMManagementFactory_getGarbageCollectorNames },
+};
+
+
+/* _Jv_java_lang_management_VMManagementFactory_init ***************************
+
+   Register native functions.
+
+*******************************************************************************/
+
+void _Jv_java_lang_management_VMManagementFactory_init(void)
+{
+       utf* u = utf_new_char("java/lang/management/VMManagementFactory");
+
+       NativeMethods& nm = VM::get_current()->get_nativemethods();
+       nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
+}
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
index a22bdacd14e24d1a29c60d9a7ca281a27edcb9f9..3a302b3fd4cad2ad6b05768792be4bdf2df38a25 100644 (file)
@@ -28,9 +28,9 @@
 #include <assert.h>
 #include <stdlib.h>
 
-#include "native/jni.h"
+#include "native/jni.hpp"
 #include "native/llni.h"
-#include "native/native.h"
+#include "native/native.hpp"
 
 #if defined(ENABLE_JNI_HEADERS)
 # include "native/vm/include/java_lang_reflect_VMConstructor.h"
@@ -148,9 +148,7 @@ JNIEXPORT jobject JNICALL Java_java_lang_reflect_VMConstructor_declaredAnnotatio
        if (declaredAnnotations == NULL) {
                java_handle_bytearray_t* annotations    = rvmc.get_annotations();
                classinfo*               declaringClass = rvmc.get_clazz();
-
-               classinfo *referer;
-               LLNI_class_get(_this, referer);
+               classinfo*               referer        = rvmc.get_Class();
 
                declaredAnnotations = Reflection::get_declaredannotations(annotations, declaringClass, referer);
 
@@ -174,9 +172,7 @@ JNIEXPORT jobjectArray JNICALL Java_java_lang_reflect_VMConstructor_getParameter
 
        java_handle_bytearray_t* parameterAnnotations = rvmc.get_parameterAnnotations();
        methodinfo* m = rvmc.get_method();
-
-       classinfo* referer;
-       LLNI_class_get((java_lang_reflect_VMConstructor*) _this, referer);
+       classinfo* referer = rvmc.get_Class();
 
        java_handle_objectarray_t* oa = Reflection::get_parameterannotations(parameterAnnotations, m, referer);
 
@@ -208,15 +204,12 @@ static JNINativeMethod methods[] = {
 
 *******************************************************************************/
 
-extern "C" {
 void _Jv_java_lang_reflect_VMConstructor_init(void)
 {
-       utf *u;
+       utf* u = utf_new_char("java/lang/reflect/VMConstructor");
 
-       u = utf_new_char("java/lang/reflect/VMConstructor");
-
-       native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+       NativeMethods& nm = VM::get_current()->get_nativemethods();
+       nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
 }
 
 
index d30e70312f6c179deb93ffb878a1bb0896a69b76..0d49fa0a3ea24b3e08e5c6bacdfdacf03189dc90 100644 (file)
@@ -28,9 +28,9 @@
 #include <assert.h>
 #include <stdint.h>
 
-#include "native/jni.h"
+#include "native/jni.hpp"
 #include "native/llni.h"
-#include "native/native.h"
+#include "native/native.hpp"
 
 #if defined(ENABLE_JNI_HEADERS)
 # include "native/vm/include/java_lang_reflect_VMField.h"
 #endif
 
 #include "vm/access.h"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/exceptions.hpp"
 #include "vm/global.h"
 #include "vm/initialize.h"
 #include "vm/javaobjects.hpp"
-#include "vm/loader.h"
+#include "vm/loader.hpp"
 #include "vm/primitive.hpp"
 #include "vm/resolve.h"
 #include "vm/string.hpp"
@@ -246,11 +246,8 @@ JNIEXPORT jobject JNICALL Java_java_lang_reflect_VMField_get(JNIEnv *env, jobjec
        java_lang_reflect_VMField rvmf(_this);
        fieldinfo* f = rvmf.get_field();
 
-       java_handle_t* ho = (java_handle_t*) o;
-
-       /* check if the field can be accessed */
-
-       if (!_field_access_check(rvmf, f, ho))
+       // Check if the field can be accessed.
+       if (!_field_access_check(rvmf, f, o))
                return NULL;
 
        imm_union value;
@@ -261,30 +258,29 @@ JNIEXPORT jobject JNICALL Java_java_lang_reflect_VMField_get(JNIEnv *env, jobjec
        case PRIMITIVETYPE_CHAR:
        case PRIMITIVETYPE_SHORT:
        case PRIMITIVETYPE_INT:
-               value.i = _field_get_int(f, ho);
+               value.i = _field_get_int(f, o);
                break;
 
        case PRIMITIVETYPE_LONG:
-               value.l = _field_get_long(f, ho);
+               value.l = _field_get_long(f, o);
                break;
 
        case PRIMITIVETYPE_FLOAT:
-               value.f = _field_get_float(f, ho);
+               value.f = _field_get_float(f, o);
                break;
 
        case PRIMITIVETYPE_DOUBLE:
-               value.d = _field_get_double(f, ho);
+               value.d = _field_get_double(f, o);
                break;
 
        case TYPE_ADR:
-               return (jobject) _field_get_handle(f, ho);
+               return (jobject) _field_get_handle(f, o);
        }
 
-       /* Now box the primitive types. */
-
+       // Now box the primitive types.
        java_handle_t* object = Primitive::box(f->parseddesc->primitivetype, value);
 
-       return (jobject) object;
+       return object;
 }
 
 
@@ -298,18 +294,14 @@ JNIEXPORT jboolean JNICALL Java_java_lang_reflect_VMField_getBoolean(JNIEnv *env
        java_lang_reflect_VMField rvmf(_this);
        fieldinfo* f = rvmf.get_field();
 
-       java_handle_t* ho = (java_handle_t*) o;
-
-       /* check if the field can be accessed */
-
-       if (!_field_access_check(rvmf, f, ho))
+       // Check if the field can be accessed.
+       if (!_field_access_check(rvmf, f, o))
                return 0;
 
-       /* check the field type and return the value */
-
+       // Check the field type and return the value.
        switch (f->parseddesc->primitivetype) {
        case PRIMITIVETYPE_BOOLEAN:
-               return (int32_t) _field_get_int(f, ho);
+               return (jint) _field_get_int(f, o);
        default:
                exceptions_throw_illegalargumentexception();
                return 0;
@@ -327,18 +319,14 @@ JNIEXPORT jbyte JNICALL Java_java_lang_reflect_VMField_getByte(JNIEnv *env, jobj
        java_lang_reflect_VMField rvmf(_this);
        fieldinfo* f = rvmf.get_field();
 
-       java_handle_t* ho = (java_handle_t*) o;
-
-       /* check if the field can be accessed */
-
-       if (!_field_access_check(rvmf, f, ho))
+       // Check if the field can be accessed.
+       if (!_field_access_check(rvmf, f, o))
                return 0;
 
-       /* check the field type and return the value */
-
+       // Check the field type and return the value.
        switch (f->parseddesc->primitivetype) {
        case PRIMITIVETYPE_BYTE:
-               return (int32_t) _field_get_int(f, ho);
+               return (jint) _field_get_int(f, o);
        default:
                exceptions_throw_illegalargumentexception();
                return 0;
@@ -356,18 +344,14 @@ JNIEXPORT jchar JNICALL Java_java_lang_reflect_VMField_getChar(JNIEnv *env, jobj
        java_lang_reflect_VMField rvmf(_this);
        fieldinfo* f = rvmf.get_field();
 
-       java_handle_t* ho = (java_handle_t*) o;
-
-       /* check if the field can be accessed */
-
-       if (!_field_access_check(rvmf, f, ho))
+       // Check if the field can be accessed.
+       if (!_field_access_check(rvmf, f, o))
                return 0;
 
-       /* check the field type and return the value */
-
+       // Check the field type and return the value.
        switch (f->parseddesc->primitivetype) {
        case PRIMITIVETYPE_CHAR:
-               return (int32_t) _field_get_int(f, ho);
+               return (jint) _field_get_int(f, o);
        default:
                exceptions_throw_illegalargumentexception();
                return 0;
@@ -385,19 +369,15 @@ JNIEXPORT jshort JNICALL Java_java_lang_reflect_VMField_getShort(JNIEnv *env, jo
        java_lang_reflect_VMField rvmf(_this);
        fieldinfo* f = rvmf.get_field();
 
-       java_handle_t* ho = (java_handle_t*) o;
-
-       /* check if the field can be accessed */
-
-       if (!_field_access_check(rvmf, f, ho))
+       // Check if the field can be accessed.
+       if (!_field_access_check(rvmf, f, o))
                return 0;
 
-       /* check the field type and return the value */
-
+       // Check the field type and return the value.
        switch (f->parseddesc->primitivetype) {
        case PRIMITIVETYPE_BYTE:
        case PRIMITIVETYPE_SHORT:
-               return (int32_t) _field_get_int(f, ho);
+               return (jint) _field_get_int(f, o);
        default:
                exceptions_throw_illegalargumentexception();
                return 0;
@@ -415,21 +395,17 @@ JNIEXPORT jint JNICALL Java_java_lang_reflect_VMField_getInt(JNIEnv *env , jobje
        java_lang_reflect_VMField rvmf(_this);
        fieldinfo* f = rvmf.get_field();
 
-       java_handle_t* ho = (java_handle_t*) o;
-
-       /* check if the field can be accessed */
-
-       if (!_field_access_check(rvmf, f, ho))
+       // Check if the field can be accessed.
+       if (!_field_access_check(rvmf, f, o))
                return 0;
 
-       /* check the field type and return the value */
-
+       // Check the field type and return the value.
        switch (f->parseddesc->primitivetype) {
        case PRIMITIVETYPE_BYTE:
        case PRIMITIVETYPE_CHAR:
        case PRIMITIVETYPE_SHORT:
        case PRIMITIVETYPE_INT:
-               return (int32_t) _field_get_int(f, ho);
+               return (jint) _field_get_int(f, o);
        default:
                exceptions_throw_illegalargumentexception();
                return 0;
@@ -447,23 +423,19 @@ JNIEXPORT jlong JNICALL Java_java_lang_reflect_VMField_getLong(JNIEnv *env, jobj
        java_lang_reflect_VMField rvmf(_this);
        fieldinfo* f = rvmf.get_field();
 
-       java_handle_t* ho = (java_handle_t*) o;
-
-       /* check if the field can be accessed */
-
-       if (!_field_access_check(rvmf, f, ho))
+       // Check if the field can be accessed.
+       if (!_field_access_check(rvmf, f, o))
                return 0;
 
-       /* check the field type and return the value */
-
+       // Check the field type and return the value.
        switch (f->parseddesc->primitivetype) {
        case PRIMITIVETYPE_BYTE:
        case PRIMITIVETYPE_CHAR:
        case PRIMITIVETYPE_SHORT:
        case PRIMITIVETYPE_INT:
-               return (int64_t) _field_get_int(f, ho);
+               return (jlong) _field_get_int(f, o);
        case PRIMITIVETYPE_LONG:
-               return (int64_t) _field_get_long(f, ho);
+               return (jlong) _field_get_long(f, o);
        default:
                exceptions_throw_illegalargumentexception();
                return 0;
@@ -481,25 +453,21 @@ JNIEXPORT jfloat JNICALL Java_java_lang_reflect_VMField_getFloat(JNIEnv *env, jo
        java_lang_reflect_VMField rvmf(_this);
        fieldinfo* f = rvmf.get_field();
 
-       java_handle_t* ho = (java_handle_t*) o;
-
-       /* check if the field can be accessed */
-
-       if (!_field_access_check(rvmf, f, ho))
+       // Check if the field can be accessed.
+       if (!_field_access_check(rvmf, f, o))
                return 0;
 
-       /* check the field type and return the value */
-
+       // Check the field type and return the value.
        switch (f->parseddesc->primitivetype) {
        case PRIMITIVETYPE_BYTE:
        case PRIMITIVETYPE_CHAR:
        case PRIMITIVETYPE_SHORT:
        case PRIMITIVETYPE_INT:
-               return (float) _field_get_int(f, ho);
+               return (jfloat) _field_get_int(f, o);
        case PRIMITIVETYPE_LONG:
-               return (float) _field_get_long(f, ho);
+               return (jfloat) _field_get_long(f, o);
        case PRIMITIVETYPE_FLOAT:
-               return (float) _field_get_float(f, ho);
+               return (jfloat) _field_get_float(f, o);
        default:
                exceptions_throw_illegalargumentexception();
                return 0;
@@ -517,27 +485,23 @@ JNIEXPORT jdouble JNICALL Java_java_lang_reflect_VMField_getDouble(JNIEnv *env ,
        java_lang_reflect_VMField rvmf(_this);
        fieldinfo* f = rvmf.get_field();
 
-       java_handle_t* ho = (java_handle_t*) o;
-
-       /* check if the field can be accessed */
-
-       if (!_field_access_check(rvmf, f, ho))
+       // Check if the field can be accessed.
+       if (!_field_access_check(rvmf, f, o))
                return 0;
 
-       /* check the field type and return the value */
-
+       // Check the field type and return the value.
        switch (f->parseddesc->primitivetype) {
        case PRIMITIVETYPE_BYTE:
        case PRIMITIVETYPE_CHAR:
        case PRIMITIVETYPE_SHORT:
        case PRIMITIVETYPE_INT:
-               return (jdouble) _field_get_int(f, ho);
+               return (jdouble) _field_get_int(f, o);
        case PRIMITIVETYPE_LONG:
-               return (jdouble) _field_get_long(f, ho);
+               return (jdouble) _field_get_long(f, o);
        case PRIMITIVETYPE_FLOAT:
-               return (jdouble) _field_get_float(f, ho);
+               return (jdouble) _field_get_float(f, o);
        case PRIMITIVETYPE_DOUBLE:
-               return (jdouble) _field_get_double(f, ho);
+               return (jdouble) _field_get_double(f, o);
        default:
                exceptions_throw_illegalargumentexception();
                return 0;
@@ -555,23 +519,18 @@ JNIEXPORT void JNICALL Java_java_lang_reflect_VMField_set(JNIEnv *env, jobject _
        java_lang_reflect_VMField rvmf(_this);
        fieldinfo* df = rvmf.get_field();
 
-       java_handle_t* ho     = (java_handle_t*) o;
-       java_handle_t* hvalue = (java_handle_t*) value;
-
        classinfo *sc;
        fieldinfo *sf;
 
-       /* check if the field can be accessed */
-
-       if (!_field_access_check(rvmf, df, ho))
+       // Check if the field can be accessed.
+       if (!_field_access_check(rvmf, df, o))
                return;
 
-       /* get the source classinfo from the object */
-
-       if (hvalue == NULL)
+       // Get the source classinfo from the object.
+       if (value == NULL)
                sc = NULL;
        else
-               LLNI_class_get(hvalue, sc);
+               LLNI_class_get(value, sc);
 
        /* The fieldid is used to set the new value, for primitive
           types the value has to be retrieved from the wrapping
@@ -588,14 +547,14 @@ JNIEXPORT void JNICALL Java_java_lang_reflect_VMField_set(JNIEnv *env, jobject _
 
                switch (sf->parseddesc->primitivetype) {
                case PRIMITIVETYPE_BOOLEAN:
-                       val = java_lang_Boolean(hvalue).get_value();
+                       val = java_lang_Boolean(value).get_value();
                        break;
                default:
                        exceptions_throw_illegalargumentexception();
                        return;
                }
 
-               _field_set_int(df, ho, val);
+               _field_set_int(df, o, val);
                return;
        }
 
@@ -607,14 +566,14 @@ JNIEXPORT void JNICALL Java_java_lang_reflect_VMField_set(JNIEnv *env, jobject _
 
                switch (sf->parseddesc->primitivetype) {
                case PRIMITIVETYPE_BYTE:
-                       val = java_lang_Byte(hvalue).get_value();
+                       val = java_lang_Byte(value).get_value();
                        break;
                default:        
                        exceptions_throw_illegalargumentexception();
                        return;
                }
 
-               _field_set_int(df, ho, val);
+               _field_set_int(df, o, val);
                return;
        }
 
@@ -626,14 +585,14 @@ JNIEXPORT void JNICALL Java_java_lang_reflect_VMField_set(JNIEnv *env, jobject _
                                   
                switch (sf->parseddesc->primitivetype) {
                case PRIMITIVETYPE_CHAR:
-                       val = java_lang_Character(hvalue).get_value();
+                       val = java_lang_Character(value).get_value();
                        break;
                default:
                        exceptions_throw_illegalargumentexception();
                        return;
                }
 
-               _field_set_int(df, ho, val);
+               _field_set_int(df, o, val);
                return;
        }
 
@@ -647,17 +606,17 @@ JNIEXPORT void JNICALL Java_java_lang_reflect_VMField_set(JNIEnv *env, jobject _
                                   
                switch (sf->parseddesc->primitivetype) {
                case PRIMITIVETYPE_BYTE:
-                       val = java_lang_Byte(hvalue).get_value();
+                       val = java_lang_Byte(value).get_value();
                        break;
                case PRIMITIVETYPE_SHORT:
-                       val = java_lang_Short(hvalue).get_value();
+                       val = java_lang_Short(value).get_value();
                        break;
                default:
                        exceptions_throw_illegalargumentexception();
                        return;
                }
 
-               _field_set_int(df, ho, val);
+               _field_set_int(df, o, val);
                return;
        }
 
@@ -671,23 +630,23 @@ JNIEXPORT void JNICALL Java_java_lang_reflect_VMField_set(JNIEnv *env, jobject _
 
                switch (sf->parseddesc->primitivetype) {
                case PRIMITIVETYPE_BYTE:
-                       val = java_lang_Byte(hvalue).get_value();
+                       val = java_lang_Byte(value).get_value();
                        break;
                case PRIMITIVETYPE_CHAR:
-                       val = java_lang_Character(hvalue).get_value();
+                       val = java_lang_Character(value).get_value();
                        break;
                case PRIMITIVETYPE_SHORT:
-                       val = java_lang_Short(hvalue).get_value();
+                       val = java_lang_Short(value).get_value();
                        break;
                case PRIMITIVETYPE_INT:
-                       val = java_lang_Integer(hvalue).get_value();
+                       val = java_lang_Integer(value).get_value();
                        break;
                default:
                        exceptions_throw_illegalargumentexception();
                        return;
                }
 
-               _field_set_int(df, ho, val);
+               _field_set_int(df, o, val);
                return;
        }
 
@@ -701,26 +660,26 @@ JNIEXPORT void JNICALL Java_java_lang_reflect_VMField_set(JNIEnv *env, jobject _
 
                switch (sf->parseddesc->primitivetype) {
                case PRIMITIVETYPE_BYTE:
-                       val = java_lang_Byte(hvalue).get_value();
+                       val = java_lang_Byte(value).get_value();
                        break;
                case PRIMITIVETYPE_CHAR:
-                       val = java_lang_Character(hvalue).get_value();
+                       val = java_lang_Character(value).get_value();
                        break;
                case PRIMITIVETYPE_SHORT:
-                       val = java_lang_Short(hvalue).get_value();
+                       val = java_lang_Short(value).get_value();
                        break;
                case PRIMITIVETYPE_INT:
-                       val = java_lang_Integer(hvalue).get_value();
+                       val = java_lang_Integer(value).get_value();
                        break;
                case PRIMITIVETYPE_LONG:
-                       val = java_lang_Long(hvalue).get_value();
+                       val = java_lang_Long(value).get_value();
                        break;
                default:
                        exceptions_throw_illegalargumentexception();
                        return;
                }
 
-               _field_set_long(df, ho, val);
+               _field_set_long(df, o, val);
                return;
        }
 
@@ -734,29 +693,29 @@ JNIEXPORT void JNICALL Java_java_lang_reflect_VMField_set(JNIEnv *env, jobject _
 
                switch (sf->parseddesc->primitivetype) {
                case PRIMITIVETYPE_BYTE:
-                       val = java_lang_Byte(hvalue).get_value();
+                       val = java_lang_Byte(value).get_value();
                        break;
                case PRIMITIVETYPE_CHAR:
-                       val = java_lang_Character(hvalue).get_value();
+                       val = java_lang_Character(value).get_value();
                        break;
                case PRIMITIVETYPE_SHORT:
-                       val = java_lang_Short(hvalue).get_value();
+                       val = java_lang_Short(value).get_value();
                        break;
                case PRIMITIVETYPE_INT:
-                       val = java_lang_Integer(hvalue).get_value();
+                       val = java_lang_Integer(value).get_value();
                        break;
                case PRIMITIVETYPE_LONG:
-                       val = java_lang_Long(hvalue).get_value();
+                       val = java_lang_Long(value).get_value();
                        break;
                case PRIMITIVETYPE_FLOAT:
-                       val = java_lang_Float(hvalue).get_value();
+                       val = java_lang_Float(value).get_value();
                        break;
                default:
                        exceptions_throw_illegalargumentexception();
                        return;
                }
 
-               _field_set_float(df, ho, val);
+               _field_set_float(df, o, val);
                return;
        }
 
@@ -770,32 +729,32 @@ JNIEXPORT void JNICALL Java_java_lang_reflect_VMField_set(JNIEnv *env, jobject _
 
                switch (sf->parseddesc->primitivetype) {
                case PRIMITIVETYPE_BYTE:
-                       val = java_lang_Byte(hvalue).get_value();
+                       val = java_lang_Byte(value).get_value();
                        break;
                case PRIMITIVETYPE_CHAR:
-                       val = java_lang_Character(hvalue).get_value();
+                       val = java_lang_Character(value).get_value();
                        break;
                case PRIMITIVETYPE_SHORT:
-                       val = java_lang_Short(hvalue).get_value();
+                       val = java_lang_Short(value).get_value();
                        break;
                case PRIMITIVETYPE_INT:
-                       val = java_lang_Integer(hvalue).get_value();
+                       val = java_lang_Integer(value).get_value();
                        break;
                case PRIMITIVETYPE_LONG:
-                       val = java_lang_Long(hvalue).get_value();
+                       val = java_lang_Long(value).get_value();
                        break;
                case PRIMITIVETYPE_FLOAT:
-                       val = java_lang_Float(hvalue).get_value();
+                       val = java_lang_Float(value).get_value();
                        break;
                case PRIMITIVETYPE_DOUBLE:
-                       val = java_lang_Double(hvalue).get_value();
+                       val = java_lang_Double(value).get_value();
                        break;
                default:
                        exceptions_throw_illegalargumentexception();
                        return;
                }
 
-               _field_set_double(df, ho, val);
+               _field_set_double(df, o, val);
                return;
        }
 
@@ -806,7 +765,7 @@ JNIEXPORT void JNICALL Java_java_lang_reflect_VMField_set(JNIEnv *env, jobject _
                /*                      if (!builtin_instanceof((java_handle_t *) value, df->class)) */
                /*                              break; */
 
-               _field_set_handle(df, ho, hvalue);
+               _field_set_handle(df, o, value);
                return;
        }
 
@@ -826,18 +785,14 @@ JNIEXPORT void JNICALL Java_java_lang_reflect_VMField_setBoolean(JNIEnv *env, jo
        java_lang_reflect_VMField rvmf(_this);
        fieldinfo* f = rvmf.get_field();
 
-       java_handle_t* ho = (java_handle_t*) o;
-
-       /* check if the field can be accessed */
-
-       if (!_field_access_check(rvmf, f, ho))
+       // Check if the field can be accessed.
+       if (!_field_access_check(rvmf, f, o))
                return;
 
-       /* check the field type and set the value */
-
+       // Check the field type and set the value.
        switch (f->parseddesc->primitivetype) {
        case PRIMITIVETYPE_BOOLEAN:
-               _field_set_int(f, ho, value);
+               _field_set_int(f, o, value);
                break;
        default:
                exceptions_throw_illegalargumentexception();
@@ -855,29 +810,25 @@ JNIEXPORT void JNICALL Java_java_lang_reflect_VMField_setByte(JNIEnv *env, jobje
        java_lang_reflect_VMField rvmf(_this);
        fieldinfo* f = rvmf.get_field();
 
-       java_handle_t* ho = (java_handle_t*) o;
-
-       /* check if the field can be accessed */
-
-       if (!_field_access_check(rvmf, f, ho))
+       // Check if the field can be accessed.
+       if (!_field_access_check(rvmf, f, o))
                return;
 
-       /* check the field type and set the value */
-
+       // Check the field type and set the value.
        switch (f->parseddesc->primitivetype) {
        case PRIMITIVETYPE_BYTE:
        case PRIMITIVETYPE_SHORT:
        case PRIMITIVETYPE_INT:
-               _field_set_int(f, ho, value);
+               _field_set_int(f, o, value);
                break;
        case PRIMITIVETYPE_LONG:
-               _field_set_long(f, ho, value);
+               _field_set_long(f, o, value);
                break;
        case PRIMITIVETYPE_FLOAT:
-               _field_set_float(f, ho, value);
+               _field_set_float(f, o, value);
                break;
        case PRIMITIVETYPE_DOUBLE:
-               _field_set_double(f, ho, value);
+               _field_set_double(f, o, value);
                break;
        default:
                exceptions_throw_illegalargumentexception();
@@ -895,28 +846,24 @@ JNIEXPORT void JNICALL Java_java_lang_reflect_VMField_setChar(JNIEnv *env, jobje
        java_lang_reflect_VMField rvmf(_this);
        fieldinfo* f = rvmf.get_field();
 
-       java_handle_t* ho = (java_handle_t*) o;
-
-       /* check if the field can be accessed */
-
-       if (!_field_access_check(rvmf, f, ho))
+       // Check if the field can be accessed.
+       if (!_field_access_check(rvmf, f, o))
                return;
 
-       /* check the field type and set the value */
-
+       // Check the field type and set the value.
        switch (f->parseddesc->primitivetype) {
        case PRIMITIVETYPE_CHAR:
        case PRIMITIVETYPE_INT:
-               _field_set_int(f, ho, value);
+               _field_set_int(f, o, value);
                break;
        case PRIMITIVETYPE_LONG:
-               _field_set_long(f, ho, value);
+               _field_set_long(f, o, value);
                break;
        case PRIMITIVETYPE_FLOAT:
-               _field_set_float(f, ho, value);
+               _field_set_float(f, o, value);
                break;
        case PRIMITIVETYPE_DOUBLE:
-               _field_set_double(f, ho, value);
+               _field_set_double(f, o, value);
                break;
        default:
                exceptions_throw_illegalargumentexception();
@@ -934,28 +881,24 @@ JNIEXPORT void JNICALL Java_java_lang_reflect_VMField_setShort(JNIEnv *env, jobj
        java_lang_reflect_VMField rvmf(_this);
        fieldinfo* f = rvmf.get_field();
 
-       java_handle_t* ho = (java_handle_t*) o;
-
-       /* check if the field can be accessed */
-
-       if (!_field_access_check(rvmf, f, ho))
+       // Check if the field can be accessed.
+       if (!_field_access_check(rvmf, f, o))
                return;
 
-       /* check the field type and set the value */
-
+       // Check the field type and set the value.
        switch (f->parseddesc->primitivetype) {
        case PRIMITIVETYPE_SHORT:
        case PRIMITIVETYPE_INT:
-               _field_set_int(f, ho, value);
+               _field_set_int(f, o, value);
                break;
        case PRIMITIVETYPE_LONG:
-               _field_set_long(f, ho, value);
+               _field_set_long(f, o, value);
                break;
        case PRIMITIVETYPE_FLOAT:
-               _field_set_float(f, ho, value);
+               _field_set_float(f, o, value);
                break;
        case PRIMITIVETYPE_DOUBLE:
-               _field_set_double(f, ho, value);
+               _field_set_double(f, o, value);
                break;
        default:
                exceptions_throw_illegalargumentexception();
@@ -973,27 +916,23 @@ JNIEXPORT void JNICALL Java_java_lang_reflect_VMField_setInt(JNIEnv *env, jobjec
        java_lang_reflect_VMField rvmf(_this);
        fieldinfo* f = rvmf.get_field();
 
-       java_handle_t* ho = (java_handle_t*) o;
-
-       /* check if the field can be accessed */
-
-       if (!_field_access_check(rvmf, f, ho))
+       // Check if the field can be accessed.
+       if (!_field_access_check(rvmf, f, o))
                return;
 
-       /* check the field type and set the value */
-
+       // Check the field type and set the value.
        switch (f->parseddesc->primitivetype) {
        case PRIMITIVETYPE_INT:
-               _field_set_int(f, ho, value);
+               _field_set_int(f, o, value);
                break;
        case PRIMITIVETYPE_LONG:
-               _field_set_long(f, ho, value);
+               _field_set_long(f, o, value);
                break;
        case PRIMITIVETYPE_FLOAT:
-               _field_set_float(f, ho, value);
+               _field_set_float(f, o, value);
                break;
        case PRIMITIVETYPE_DOUBLE:
-               _field_set_double(f, ho, value);
+               _field_set_double(f, o, value);
                break;
        default:
                exceptions_throw_illegalargumentexception();
@@ -1011,24 +950,20 @@ JNIEXPORT void JNICALL Java_java_lang_reflect_VMField_setLong(JNIEnv *env, jobje
        java_lang_reflect_VMField rvmf(_this);
        fieldinfo* f = rvmf.get_field();
 
-       java_handle_t* ho = (java_handle_t*) o;
-
-       /* check if the field can be accessed */
-
-       if (!_field_access_check(rvmf, f, ho))
+       // Check if the field can be accessed.
+       if (!_field_access_check(rvmf, f, o))
                return;
 
-       /* check the field type and set the value */
-
+       // Check the field type and set the value.
        switch (f->parseddesc->primitivetype) {
        case PRIMITIVETYPE_LONG:
-               _field_set_long(f, ho, value);
+               _field_set_long(f, o, value);
                break;
        case PRIMITIVETYPE_FLOAT:
-               _field_set_float(f, ho, value);
+               _field_set_float(f, o, value);
                break;
        case PRIMITIVETYPE_DOUBLE:
-               _field_set_double(f, ho, value);
+               _field_set_double(f, o, value);
                break;
        default:
                exceptions_throw_illegalargumentexception();
@@ -1046,21 +981,17 @@ JNIEXPORT void JNICALL Java_java_lang_reflect_VMField_setFloat(JNIEnv *env, jobj
        java_lang_reflect_VMField rvmf(_this);
        fieldinfo* f = rvmf.get_field();
 
-       java_handle_t* ho = (java_handle_t*) o;
-
-       /* check if the field can be accessed */
-
-       if (!_field_access_check(rvmf, f, ho))
+       // Check if the field can be accessed.
+       if (!_field_access_check(rvmf, f, o))
                return;
 
-       /* check the field type and set the value */
-
+       // Check the field type and set the value.
        switch (f->parseddesc->primitivetype) {
        case PRIMITIVETYPE_FLOAT:
-               _field_set_float(f, ho, value);
+               _field_set_float(f, o, value);
                break;
        case PRIMITIVETYPE_DOUBLE:
-               _field_set_double(f, ho, value);
+               _field_set_double(f, o, value);
                break;
        default:
                exceptions_throw_illegalargumentexception();
@@ -1078,18 +1009,14 @@ JNIEXPORT void JNICALL Java_java_lang_reflect_VMField_setDouble(JNIEnv *env, job
        java_lang_reflect_VMField rvmf(_this);
        fieldinfo* f = rvmf.get_field();
 
-       java_handle_t* ho = (java_handle_t*) o;
-
-       /* check if the field can be accessed */
-
-       if (!_field_access_check(rvmf, f, ho))
+       // Check if the field can be accessed.
+       if (!_field_access_check(rvmf, f, o))
                return;
 
-       /* check the field type and set the value */
-
+       // Check the field type and set the value.
        switch (f->parseddesc->primitivetype) {
        case PRIMITIVETYPE_DOUBLE:
-               _field_set_double(f, ho, value);
+               _field_set_double(f, o, value);
                break;
        default:
                exceptions_throw_illegalargumentexception();
@@ -1114,7 +1041,7 @@ JNIEXPORT jstring JNICALL Java_java_lang_reflect_VMField_getSignature(JNIEnv *en
 
        /* in error case o is NULL */
 
-       return (jstring) o;
+       return o;
 }
 
 
@@ -1134,9 +1061,7 @@ JNIEXPORT jobject JNICALL Java_java_lang_reflect_VMField_declaredAnnotations(JNI
        if (declaredAnnotations == NULL) {
                java_handle_bytearray_t* annotations    = rvmf.get_annotations();
                classinfo*               declaringClass = rvmf.get_clazz();
-
-               classinfo* referer;
-               LLNI_class_get(_this, referer);
+               classinfo*               referer        = rvmf.get_Class();
 
                declaredAnnotations = Reflection::get_declaredannotations(annotations, declaringClass, referer);
 
@@ -1186,16 +1111,12 @@ static const JNINativeMethod methods[] = {
 
 *******************************************************************************/
 
-// FIXME
-extern "C" {
 void _Jv_java_lang_reflect_VMField_init(void)
 {
-       utf *u;
-
-       u = utf_new_char("java/lang/reflect/VMField");
+       utf* u = utf_new_char("java/lang/reflect/VMField");
 
-       native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+       NativeMethods& nm = VM::get_current()->get_nativemethods();
+       nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
 }
 
 
index cafb69942680ad1dbb7bb9818f91ecb1a43f3273..c569915f28f61579d3912c69b574a68ee8a6dd13 100644 (file)
@@ -31,9 +31,9 @@
 #include "vm/vm.hpp"
 #endif
 
-#include "native/jni.h"
+#include "native/jni.hpp"
 #include "native/llni.h"
-#include "native/native.h"
+#include "native/native.hpp"
 
 #if defined(ENABLE_JNI_HEADERS)
 # include "native/vm/include/java_lang_reflect_VMMethod.h"
@@ -42,7 +42,7 @@
 #include "native/vm/reflection.hpp"
 
 #include "vm/access.h"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/class.h"
 #include "vm/exceptions.hpp"
 #include "vm/global.h"
@@ -193,8 +193,7 @@ JNIEXPORT jobject JNICALL Java_java_lang_reflect_VMMethod_getDefaultValue(JNIEnv
                        return NULL;
                }
 
-               classinfo *referer;
-               LLNI_class_get((java_lang_reflect_VMMethod *) _this, referer);
+               classinfo *referer = rvmm.get_Class();
 
                m_parseAnnotationDefault = class_resolveclassmethod(
                        class_sun_reflect_annotation_AnnotationParser,
@@ -232,9 +231,7 @@ JNIEXPORT jobject JNICALL Java_java_lang_reflect_VMMethod_declaredAnnotations(JN
        if (declaredAnnotations == NULL) {
                java_handle_bytearray_t* annotations    = rvmm.get_annotations();
                classinfo*               declaringClass = rvmm.get_clazz();
-
-               classinfo *referer;
-               LLNI_class_get((java_lang_reflect_VMMethod *) _this, referer);
+               classinfo*               referer        = rvmm.get_Class();
 
                declaredAnnotations = Reflection::get_declaredannotations(annotations, declaringClass, referer);
 
@@ -255,9 +252,7 @@ JNIEXPORT jobjectArray JNICALL Java_java_lang_reflect_VMMethod_getParameterAnnot
        java_lang_reflect_VMMethod rvmm(_this);
        java_handle_bytearray_t* parameterAnnotations = rvmm.get_parameterAnnotations();
        methodinfo* m = rvmm.get_method();
-
-       classinfo* referer;
-       LLNI_class_get((java_lang_reflect_VMMethod *) _this, referer);
+       classinfo* referer = rvmm.get_Class();
 
        java_handle_objectarray_t* oa = Reflection::get_parameterannotations(parameterAnnotations, m, referer);
        return (jobjectArray) oa;
@@ -290,16 +285,12 @@ static JNINativeMethod methods[] = {
 
 *******************************************************************************/
 
-// FIXME
-extern "C" {
 void _Jv_java_lang_reflect_VMMethod_init(void)
 {
-       utf *u;
+       utf* u = utf_new_char("java/lang/reflect/VMMethod");
 
-       u = utf_new_char("java/lang/reflect/VMMethod");
-
-       native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+       NativeMethods& nm = VM::get_current()->get_nativemethods();
+       nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
 }
 
 
index f40678c1489795bc1abe303b2036248d4596bdc6..29f894bfb482023edd55305837cffa0bc38d577f 100644 (file)
@@ -27,8 +27,8 @@
 
 #include <stdlib.h>
 
-#include "native/jni.h"
-#include "native/native.h"
+#include "native/jni.hpp"
+#include "native/native.hpp"
 
 // FIXME
 //#include "native/include/java_lang_reflect_VMProxy.h"
@@ -51,16 +51,16 @@ static JNINativeMethod methods[] = {
 
 *******************************************************************************/
 
+#if 0
 void _Jv_java_lang_reflect_VMProxy_init(void)
 {
-#if 0
        utf *u;
 
        u = utf_new_char("java/lang/reflect/VMProxy");
 
        native_method_register(u, methods, NATIVE_METHODS_COUNT);
-#endif
 }
+#endif
 
 
 #if 0
index abd1ed6c36d745c34de2cfbd640dd69eeec478b0..89977192987bbf42d61083a7dd87af3d40db4e58 100644 (file)
@@ -27,8 +27,8 @@
 
 #include <stdint.h>
 
-#include "native/jni.h"
-#include "native/native.h"
+#include "native/jni.hpp"
+#include "native/native.hpp"
 
 #if defined(ENABLE_JNI_HEADERS)
 # include "native/vm/include/java_security_VMAccessController.h"
@@ -69,16 +69,12 @@ static JNINativeMethod methods[] = {
 
 *******************************************************************************/
 
-// FIXME
-extern "C" {
 void _Jv_java_security_VMAccessController_init(void)
 {
-       utf *u;
-
-       u = utf_new_char("java/security/VMAccessController");
+       utf* u = utf_new_char("java/security/VMAccessController");
 
-       native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+       NativeMethods& nm = VM::get_current()->get_nativemethods();
+       nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
 }
 
 
index c95ad1845a9da8c14e5c3295079cd477ad3f4981..8ee6b74ca3831c41563f018e656c8733281eb1a1 100644 (file)
 
 #include <stdint.h>
 
-#include "native/jni.h"
-#include "native/native.h"
+#include "native/jni.hpp"
+#include "native/native.hpp"
 
 #if defined(ENABLE_JNI_HEADERS)
 # include "native/include/java_util_concurrent_atomic_AtomicLong.h"
 #endif
 
 #include "vm/utf8.h"
+#include "vm/vm.hpp"
 
 
 // Native functions are exported as C functions.
@@ -67,16 +68,12 @@ static JNINativeMethod methods[] = {
 
 *******************************************************************************/
 
-// FIXME
-extern "C" {
 void _Jv_java_util_concurrent_atomic_AtomicLong_init(void)
 {
-       utf *u;
-
-       u = utf_new_char("java/util/concurrent/atomic/AtomicLong");
+       utf* u = utf_new_char("java/util/concurrent/atomic/AtomicLong");
 
-       native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+       NativeMethods& nm = VM::get_current()->get_nativemethods();
+       nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
 }
 
 
index ad48b2fda428abbc60a71ba05524588844245219..418fb50f92687c38540ae3af5f540dd6159e1d7a 100644 (file)
@@ -42,9 +42,9 @@
 
 #include "mm/memory.h"
 
-#include "native/jni.h"
+#include "native/jni.hpp"
 #include "native/llni.h"
-#include "native/native.h"
+#include "native/native.hpp"
 
 // FIXME
 //#include "native/include/sun_reflect_ConstantPool.h"
@@ -416,12 +416,12 @@ static JNINativeMethod methods[] = {
 
 *******************************************************************************/
 
-// FIXME
-extern "C" {
 void _Jv_sun_reflect_ConstantPool_init(void)
 {
-       native_method_register(utf_new_char("sun/reflect/ConstantPool"), methods, NATIVE_METHODS_COUNT);
-}
+       utf* u = utf_new_char("sun/reflect/ConstantPool");
+
+       NativeMethods& nm = VM::get_current()->get_nativemethods();
+       nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
 }
 
 
diff --git a/src/native/vm/nativevm.c b/src/native/vm/nativevm.c
deleted file mode 100644 (file)
index 563cce4..0000000
+++ /dev/null
@@ -1,225 +0,0 @@
-/* src/native/vm/nativevm.c - register the native functions
-
-   Copyright (C) 2007, 2008
-   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
-
-   This file is part of CACAO.
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2, or (at
-   your option) any later version.
-
-   This program is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-   02110-1301, USA.
-
-*/
-
-
-#include "config.h"
-
-#include <stdint.h>
-
-#include "native/vm/nativevm.h"
-
-#include "vm/class.h"
-#include "vm/initialize.h"
-#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/native.h"
-
-# include "native/vm/openjdk/hpi.h"
-
-# include "vm/globals.hpp"
-# include "vm/properties.h"
-# include "vm/utf8.h"
-# include "vm/vm.hpp"
-#endif
-
-
-/* nativevm_preinit ************************************************************
-
-   Pre-initialize the implementation specific native stuff.
-
-*******************************************************************************/
-
-void nativevm_preinit(void)
-{
-       /* Register native methods of all classes implemented. */
-
-#if defined(ENABLE_JAVASE)
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-
-       TRACESUBSYSTEMINITIALIZATION("nativevm_preinit");
-
-       _Jv_gnu_classpath_VMStackWalker_init();
-       _Jv_gnu_classpath_VMSystemProperties_init();
-       _Jv_gnu_java_lang_VMCPStringBuilder_init();
-       _Jv_gnu_java_lang_management_VMClassLoadingMXBeanImpl_init();
-       _Jv_gnu_java_lang_management_VMMemoryMXBeanImpl_init();
-       _Jv_gnu_java_lang_management_VMRuntimeMXBeanImpl_init();
-       _Jv_gnu_java_lang_management_VMThreadMXBeanImpl_init();
-       _Jv_java_lang_VMClass_init();
-       _Jv_java_lang_VMClassLoader_init();
-       _Jv_java_lang_VMObject_init();
-       _Jv_java_lang_VMRuntime_init();
-       _Jv_java_lang_VMSystem_init();
-       _Jv_java_lang_VMString_init();
-       _Jv_java_lang_VMThread_init();
-       _Jv_java_lang_VMThrowable_init();
-       _Jv_java_lang_management_VMManagementFactory_init();
-       _Jv_java_lang_reflect_VMConstructor_init();
-       _Jv_java_lang_reflect_VMField_init();
-       _Jv_java_lang_reflect_VMMethod_init();
-       _Jv_java_lang_reflect_VMProxy_init();
-       _Jv_java_security_VMAccessController_init();
-       _Jv_java_util_concurrent_atomic_AtomicLong_init();
-       _Jv_sun_misc_Unsafe_init();
-
-#if defined(ENABLE_ANNOTATIONS)
-       _Jv_sun_reflect_ConstantPool_init();
-#endif
-
-# elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-
-       const char* boot_library_path;
-       int   len;
-       char* p;
-       utf*  u;
-       void* handle;
-
-       TRACESUBSYSTEMINITIALIZATION("nativevm_preinit");
-
-       /* Load libjava.so */
-
-       boot_library_path = properties_get("sun.boot.library.path");
-
-       len =
-               os_strlen(boot_library_path) +
-               os_strlen("/libjava.so") +
-               os_strlen("0");
-
-       p = MNEW(char, len);
-
-       os_strcpy(p, boot_library_path);
-       os_strcat(p, "/libjava.so");
-
-       u = utf_new_char(p);
-
-       handle = native_library_open(u);
-
-       if (handle == NULL)
-               vm_abort("nativevm_init: failed to open libjava.so at: %s", p);
-
-       MFREE(p, char, len);
-
-       native_library_add(u, NULL, handle);
-
-       /* Initialize the HPI. */
-
-       hpi_initialize();
-
-       _Jv_sun_misc_Unsafe_init();
-
-# else
-#  error unknown classpath configuration
-# endif
-
-#elif defined(ENABLE_JAVAME_CLDC1_1)
-
-       TRACESUBSYSTEMINITIALIZATION("nativevm_preinit");
-
-       _Jv_com_sun_cldc_io_ResourceInputStream_init();
-       _Jv_com_sun_cldc_io_j2me_socket_Protocol_init();
-       _Jv_com_sun_cldchi_io_ConsoleOutputStream_init();
-       _Jv_com_sun_cldchi_jvm_JVM_init();
-       _Jv_java_lang_Class_init();
-       _Jv_java_lang_Double_init();
-       _Jv_java_lang_Float_init();
-       _Jv_java_lang_Math_init();
-       _Jv_java_lang_Object_init();
-       _Jv_java_lang_Runtime_init();
-       _Jv_java_lang_String_init();
-       _Jv_java_lang_System_init();
-       _Jv_java_lang_Thread_init();
-       _Jv_java_lang_Throwable_init();
-
-#else
-# error unknown Java configuration
-#endif
-}
-
-
-/* nativevm_init ***************************************************************
-
-   Initialize the implementation specific native stuff.
-
-*******************************************************************************/
-
-void nativevm_init(void)
-{
-#if defined(ENABLE_JAVASE)
-
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-
-       TRACESUBSYSTEMINITIALIZATION("nativevm_init");
-
-       /* nothing to do */
-
-# elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-
-       methodinfo *m;
-
-       TRACESUBSYSTEMINITIALIZATION("nativevm_init");
-
-       m = class_resolveclassmethod(class_java_lang_System,
-                                                                utf_new_char("initializeSystemClass"),
-                                                                utf_void__void,
-                                                                class_java_lang_Object,
-                                                                false);
-
-       if (m == NULL)
-               vm_abort("nativevm_init: Error resolving java.lang.System.initializeSystemClass()");
-
-       (void) vm_call_method(m, NULL);
-
-# else
-#  error unknown classpath configuration
-# endif
-
-#elif defined(ENABLE_JAVAME_CLDC1_1)
-
-       TRACESUBSYSTEMINITIALIZATION("nativevm_init");
-
-       /* nothing to do */
-
-#else
-# error unknown Java configuration
-#endif
-}
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- */
diff --git a/src/native/vm/nativevm.cpp b/src/native/vm/nativevm.cpp
new file mode 100644 (file)
index 0000000..4397364
--- /dev/null
@@ -0,0 +1,213 @@
+/* src/native/vm/nativevm.cpp - Register native VM interface functions.
+
+   Copyright (C) 2007, 2008
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+   This file is part of CACAO.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+*/
+
+
+#include "config.h"
+
+#include <stdint.h>
+
+#include "native/vm/nativevm.hpp"
+
+#include "vm/class.h"
+#include "vm/initialize.h"
+#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/native.hpp"
+
+# include "native/vm/openjdk/hpi.hpp"
+
+# include "vm/globals.hpp"
+# include "vm/properties.hpp"
+# include "vm/utf8.h"
+# include "vm/vm.hpp"
+#endif
+
+
+/* nativevm_preinit ************************************************************
+
+   Pre-initialize the implementation specific native stuff.
+
+*******************************************************************************/
+
+void nativevm_preinit(void)
+{
+       TRACESUBSYSTEMINITIALIZATION("nativevm_preinit");
+
+       /* Register native methods of all classes implemented. */
+
+#if defined(ENABLE_JAVASE)
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+
+       _Jv_gnu_classpath_VMStackWalker_init();
+       _Jv_gnu_classpath_VMSystemProperties_init();
+       _Jv_gnu_java_lang_VMCPStringBuilder_init();
+       _Jv_gnu_java_lang_management_VMClassLoadingMXBeanImpl_init();
+       _Jv_gnu_java_lang_management_VMMemoryMXBeanImpl_init();
+       _Jv_gnu_java_lang_management_VMRuntimeMXBeanImpl_init();
+       _Jv_gnu_java_lang_management_VMThreadMXBeanImpl_init();
+       _Jv_java_lang_VMClass_init();
+       _Jv_java_lang_VMClassLoader_init();
+       _Jv_java_lang_VMObject_init();
+       _Jv_java_lang_VMRuntime_init();
+       _Jv_java_lang_VMSystem_init();
+       _Jv_java_lang_VMString_init();
+       _Jv_java_lang_VMThread_init();
+       _Jv_java_lang_VMThrowable_init();
+       _Jv_java_lang_management_VMManagementFactory_init();
+       _Jv_java_lang_reflect_VMConstructor_init();
+       _Jv_java_lang_reflect_VMField_init();
+       _Jv_java_lang_reflect_VMMethod_init();
+       //_Jv_java_lang_reflect_VMProxy_init();
+       _Jv_java_security_VMAccessController_init();
+       _Jv_java_util_concurrent_atomic_AtomicLong_init();
+       _Jv_sun_misc_Unsafe_init();
+
+#if defined(ENABLE_ANNOTATIONS)
+       _Jv_sun_reflect_ConstantPool_init();
+#endif
+
+# elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+
+       // Load libjava.so
+       VM* vm = VM::get_current();
+       Properties& properties = vm->get_properties();
+       const char* boot_library_path = properties.get("sun.boot.library.path");
+
+       size_t len =
+               os::strlen(boot_library_path) +
+               os::strlen("/libjava.so") +
+               os::strlen("0");
+
+       char* p = MNEW(char, len);
+
+       os::strcpy(p, boot_library_path);
+       os::strcat(p, "/libjava.so");
+
+       utf* u = utf_new_char(p);
+
+       NativeLibrary nl(u);
+       void* handle = nl.open();
+
+       if (handle == NULL)
+               os::abort("nativevm_init: failed to open libjava.so at: %s", p);
+
+       MFREE(p, char, len);
+
+       NativeLibraries& nls = vm->get_nativelibraries();
+       nls.add(nl);
+
+       // Initialize the HPI.
+       HPI& hpi = vm->get_hpi();
+       hpi.initialize();
+
+       _Jv_sun_misc_Unsafe_init();
+
+# else
+#  error unknown classpath configuration
+# endif
+
+#elif defined(ENABLE_JAVAME_CLDC1_1)
+
+       _Jv_com_sun_cldc_io_ResourceInputStream_init();
+       _Jv_com_sun_cldc_io_j2me_socket_Protocol_init();
+       _Jv_com_sun_cldchi_io_ConsoleOutputStream_init();
+       _Jv_com_sun_cldchi_jvm_JVM_init();
+       _Jv_java_lang_Class_init();
+       _Jv_java_lang_Double_init();
+       _Jv_java_lang_Float_init();
+       _Jv_java_lang_Math_init();
+       _Jv_java_lang_Object_init();
+       _Jv_java_lang_Runtime_init();
+       _Jv_java_lang_String_init();
+       _Jv_java_lang_System_init();
+       _Jv_java_lang_Thread_init();
+       _Jv_java_lang_Throwable_init();
+
+#else
+# error unknown Java configuration
+#endif
+}
+
+
+/* nativevm_init ***************************************************************
+
+   Initialize the implementation specific native stuff.
+
+*******************************************************************************/
+
+void nativevm_init(void)
+{
+       TRACESUBSYSTEMINITIALIZATION("nativevm_init");
+
+#if defined(ENABLE_JAVASE)
+
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+
+       // Nothing to do.
+
+# elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+
+       methodinfo* m = class_resolveclassmethod(class_java_lang_System,
+                                                                                        utf_new_char("initializeSystemClass"),
+                                                                                        utf_void__void,
+                                                                                        class_java_lang_Object,
+                                                                                        false);
+
+       if (m == NULL)
+               os::abort("nativevm_init: Error resolving java.lang.System.initializeSystemClass()");
+
+       (void) vm_call_method(m, NULL);
+
+# else
+#  error unknown classpath configuration
+# endif
+
+#elif defined(ENABLE_JAVAME_CLDC1_1)
+
+       // Nothing to do.
+
+#else
+# error unknown Java configuration
+#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:
+ */
diff --git a/src/native/vm/nativevm.h b/src/native/vm/nativevm.h
deleted file mode 100644 (file)
index de4ba48..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-/* src/native/vm/nativevm.h - register the native 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 _NATIVEVM_H
-#define _NATIVEVM_H
-
-#include "config.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "vm/types.h"
-
-#include "vm/global.h"
-
-
-/* function prototypes ********************************************************/
-
-void nativevm_preinit(void);
-void nativevm_init(void);
-
-#if defined(ENABLE_JAVASE)
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-
-void _Jv_gnu_classpath_VMStackWalker_init();
-void _Jv_gnu_classpath_VMSystemProperties_init();
-void _Jv_gnu_java_lang_VMCPStringBuilder_init();
-void _Jv_gnu_java_lang_management_VMClassLoadingMXBeanImpl_init();
-void _Jv_gnu_java_lang_management_VMMemoryMXBeanImpl_init();
-void _Jv_gnu_java_lang_management_VMRuntimeMXBeanImpl_init();
-void _Jv_gnu_java_lang_management_VMThreadMXBeanImpl_init();
-void _Jv_java_lang_VMClass_init();
-void _Jv_java_lang_VMClassLoader_init();
-void _Jv_java_lang_VMObject_init();
-void _Jv_java_lang_VMRuntime_init();
-void _Jv_java_lang_VMString_init();
-void _Jv_java_lang_VMSystem_init();
-void _Jv_java_lang_VMThread_init();
-void _Jv_java_lang_VMThrowable_init();
-void _Jv_java_lang_management_VMManagementFactory_init();
-void _Jv_java_lang_reflect_VMConstructor_init();
-void _Jv_java_lang_reflect_VMField_init();
-void _Jv_java_lang_reflect_VMMethod_init();
-void _Jv_java_lang_reflect_VMProxy_init();
-void _Jv_java_security_VMAccessController_init();
-void _Jv_java_util_concurrent_atomic_AtomicLong_init();
-void _Jv_sun_misc_Unsafe_init();
-
-#if defined(ENABLE_ANNOTATIONS)
-void _Jv_sun_reflect_ConstantPool_init();
-#endif
-
-# elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-
-void _Jv_sun_misc_Unsafe_init();
-
-# else
-#  error unknown classpath configuration
-# endif
-
-#elif defined(ENABLE_JAVAME_CLDC1_1)
-
-void _Jv_com_sun_cldc_io_ResourceInputStream_init();
-void _Jv_com_sun_cldc_io_j2me_socket_Protocol_init();
-void _Jv_com_sun_cldchi_io_ConsoleOutputStream_init();
-void _Jv_com_sun_cldchi_jvm_JVM_init();
-void _Jv_java_lang_Class_init();
-void _Jv_java_lang_Double_init();
-void _Jv_java_lang_Float_init();
-void _Jv_java_lang_Math_init();
-void _Jv_java_lang_Object_init();
-void _Jv_java_lang_Runtime_init();
-void _Jv_java_lang_String_init();
-void _Jv_java_lang_System_init();
-void _Jv_java_lang_Thread_init();
-void _Jv_java_lang_Throwable_init();
-
-#else
-# error unknown Java configuration
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _NATIVEVM_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:
- */
diff --git a/src/native/vm/nativevm.hpp b/src/native/vm/nativevm.hpp
new file mode 100644 (file)
index 0000000..826643f
--- /dev/null
@@ -0,0 +1,111 @@
+/* src/native/vm/nativevm.hpp - Register native VM interface 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 _NATIVEVM_HPP
+#define _NATIVEVM_HPP
+
+#include "config.h"
+
+/* function prototypes ********************************************************/
+
+void nativevm_preinit(void);
+void nativevm_init(void);
+
+#if defined(ENABLE_JAVASE)
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+
+void _Jv_gnu_classpath_VMStackWalker_init();
+void _Jv_gnu_classpath_VMSystemProperties_init();
+void _Jv_gnu_java_lang_VMCPStringBuilder_init();
+void _Jv_gnu_java_lang_management_VMClassLoadingMXBeanImpl_init();
+void _Jv_gnu_java_lang_management_VMMemoryMXBeanImpl_init();
+void _Jv_gnu_java_lang_management_VMRuntimeMXBeanImpl_init();
+void _Jv_gnu_java_lang_management_VMThreadMXBeanImpl_init();
+void _Jv_java_lang_VMClass_init();
+void _Jv_java_lang_VMClassLoader_init();
+void _Jv_java_lang_VMObject_init();
+void _Jv_java_lang_VMRuntime_init();
+void _Jv_java_lang_VMString_init();
+void _Jv_java_lang_VMSystem_init();
+void _Jv_java_lang_VMThread_init();
+void _Jv_java_lang_VMThrowable_init();
+void _Jv_java_lang_management_VMManagementFactory_init();
+void _Jv_java_lang_reflect_VMConstructor_init();
+void _Jv_java_lang_reflect_VMField_init();
+void _Jv_java_lang_reflect_VMMethod_init();
+void _Jv_java_lang_reflect_VMProxy_init();
+void _Jv_java_security_VMAccessController_init();
+void _Jv_java_util_concurrent_atomic_AtomicLong_init();
+void _Jv_sun_misc_Unsafe_init();
+
+#if defined(ENABLE_ANNOTATIONS)
+void _Jv_sun_reflect_ConstantPool_init();
+#endif
+
+# elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+
+void _Jv_sun_misc_Unsafe_init();
+
+# else
+#  error unknown classpath configuration
+# endif
+
+#elif defined(ENABLE_JAVAME_CLDC1_1)
+
+void _Jv_com_sun_cldc_io_ResourceInputStream_init();
+void _Jv_com_sun_cldc_io_j2me_socket_Protocol_init();
+void _Jv_com_sun_cldchi_io_ConsoleOutputStream_init();
+void _Jv_com_sun_cldchi_jvm_JVM_init();
+void _Jv_java_lang_Class_init();
+void _Jv_java_lang_Double_init();
+void _Jv_java_lang_Float_init();
+void _Jv_java_lang_Math_init();
+void _Jv_java_lang_Object_init();
+void _Jv_java_lang_Runtime_init();
+void _Jv_java_lang_String_init();
+void _Jv_java_lang_System_init();
+void _Jv_java_lang_Thread_init();
+void _Jv_java_lang_Throwable_init();
+
+#else
+# error unknown Java configuration
+#endif
+
+#endif // _NATIVEVM_HPP
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
index 49677897a94bc12b82aeef1f2bced9f6ebb84264..1e5bfd3bd19ff7cab27660b9c572ac09b8e0c953 100644 (file)
@@ -29,9 +29,11 @@ noinst_LTLIBRARIES = \
        libnativevmcore.la
 
 libnativevmcore_la_SOURCES = \
-       hpi.c \
-       hpi.h \
-       jvm.cpp
+       hpi.cpp \
+       hpi.hpp \
+       jvm.cpp \
+       management.cpp \
+       management.hpp
 
 
 ## Local variables:
diff --git a/src/native/vm/openjdk/hpi.c b/src/native/vm/openjdk/hpi.c
deleted file mode 100644 (file)
index 7b89c59..0000000
+++ /dev/null
@@ -1,201 +0,0 @@
-/* src/native/vm/openjdk/hpi.c - HotSpot HPI interface functions
-
-   Copyright (C) 2008
-   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
-
-   This file is part of CACAO.
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2, or (at
-   your option) any later version.
-
-   This program is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-   02110-1301, USA.
-
-*/
-
-
-#include "config.h"
-
-/* We include hpi_md.h before hpi.h as the latter includes the
-   former. */
-
-#include INCLUDE_HPI_MD_H
-#include INCLUDE_HPI_H
-
-#include "mm/memory.h"
-
-#include "native/jni.h"
-#include "native/native.h"
-
-#include "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"
-
-
-/* VM callback functions ******************************************************/
-
-static vm_calls_t callbacks = {
-       /* TODO What should we use here? */
-/*   jio_fprintf, */
-/*   unimplemented_panic, */
-/*   unimplemented_monitorRegister, */
-       NULL,
-       NULL,
-       NULL,
-       
-       NULL, /* unused */
-       NULL, /* unused */
-       NULL  /* unused */
-};
-
-
-/* HPI interfaces *************************************************************/
-
-GetInterfaceFunc      hpi_get_interface = NULL;
-HPI_FileInterface    *hpi_file          = NULL;
-HPI_SocketInterface  *hpi_socket        = NULL;
-HPI_LibraryInterface *hpi_library       = NULL;
-HPI_SystemInterface  *hpi_system        = NULL;
-
-
-/* hpi_initialize **************************************************************
-
-   Initialize the Host Porting Interface (HPI).
-
-*******************************************************************************/
-
-void hpi_initialize(void)
-{
-       const char* boot_library_path;
-       int   len;
-       char* p;
-       utf*  u;
-       void* handle;
-       void* dll_initialize;
-       int   result;
-
-    jint (JNICALL * DLL_Initialize)(GetInterfaceFunc *, void *);
-
-       TRACESUBSYSTEMINITIALIZATION("hpi_init");
-
-       /* Load libhpi.so */
-
-       boot_library_path = properties_get("sun.boot.library.path");
-
-       len =
-               os_strlen(boot_library_path) +
-               os_strlen("/native_threads/libhpi.so") +
-               os_strlen("0");
-
-       p = MNEW(char, len);
-
-       os_strcpy(p, boot_library_path);
-       os_strcat(p, "/native_threads/libhpi.so");
-
-       u = utf_new_char(p);
-
-    if (opt_TraceHPI)
-               log_println("hpi_init: Loading HPI %s ", p);
-
-       MFREE(p, char, len);
-
-       handle = native_library_open(u);
-
-       if (handle == NULL)
-               if (opt_TraceHPI)
-                       vm_abort("hpi_init: HPI open failed");
-
-       /* Resolve the DLL_Initialize function from the library. */
-
-       dll_initialize = os_dlsym(handle, "DLL_Initialize");
-
-    DLL_Initialize = (jint (JNICALL *)(GetInterfaceFunc *, void *)) (intptr_t) dll_initialize;
-
-    if (opt_TraceHPI && DLL_Initialize == NULL)
-               log_println("hpi_init: HPI dlsym of DLL_Initialize failed: %s", os_dlerror());
-
-    if (DLL_Initialize == NULL ||
-        (*DLL_Initialize)(&hpi_get_interface, &callbacks) < 0) {
-
-        if (opt_TraceHPI)
-                       vm_abort("hpi_init: HPI DLL_Initialize failed");
-    }
-
-       native_library_add(u, NULL, handle);
-
-    if (opt_TraceHPI)
-               log_println("hpi_init: HPI loaded successfully");
-
-       /* Resolve the interfaces. */
-       /* NOTE: The intptr_t-case is only to prevent the a compiler
-          warning with -O2: warning: dereferencing type-punned pointer
-          will break strict-aliasing rules */
-
-       result = (*hpi_get_interface)((void **) (intptr_t) &hpi_file, "File", 1);
-
-       if (result != 0)
-               vm_abort("hpi_init: Can't find HPI_FileInterface");
-
-       result = (*hpi_get_interface)((void **) (intptr_t) &hpi_library, "Library", 1);
-
-       if (result != 0)
-               vm_abort("hpi_init: Can't find HPI_LibraryInterface");
-
-       result = (*hpi_get_interface)((void **) (intptr_t) &hpi_system, "System", 1);
-
-       if (result != 0)
-               vm_abort("hpi_init: Can't find HPI_SystemInterface");
-}
-
-
-/* hpi_initialize_socket_library ***********************************************
-
-   Initialize the library Host Porting Interface (HPI).
-
-*******************************************************************************/
-
-int hpi_initialize_socket_library(void)
-{
-       int result;
-
-       /* Resolve the socket library interface. */
-
-       result = (*hpi_get_interface)((void **) (intptr_t) &hpi_socket, "Socket", 1);
-
-       if (result != 0) {
-               if (opt_TraceHPI)
-                       log_println("hpi_initialize_socket_library: Can't find HPI_SocketInterface");
-
-               return JNI_ERR;
-       }
-
-       return JNI_OK;
-}
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
diff --git a/src/native/vm/openjdk/hpi.cpp b/src/native/vm/openjdk/hpi.cpp
new file mode 100644 (file)
index 0000000..ad6eec5
--- /dev/null
@@ -0,0 +1,180 @@
+/* src/native/vm/openjdk/hpi.cpp - HotSpot HPI interface functions
+
+   Copyright (C) 2008
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+   This file is part of CACAO.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+*/
+
+
+#include "config.h"
+
+// Include this one early.
+#include "native/vm/openjdk/hpi.hpp"
+
+#include "mm/memory.h"
+
+#include "native/native.hpp"
+
+#include "vm/options.h"
+#include "vm/os.hpp"
+#include "vm/properties.hpp"
+#include "vm/utf8.h"
+#include "vm/vm.hpp"
+
+
+/* VM callback functions ******************************************************/
+
+static vm_calls_t callbacks = {
+       /* TODO What should we use here? */
+/*   jio_fprintf, */
+/*   unimplemented_panic, */
+/*   unimplemented_monitorRegister, */
+       NULL,
+       NULL,
+       NULL,
+       
+       NULL, /* unused */
+       NULL, /* unused */
+       NULL  /* unused */
+};
+
+
+/**
+ * Initialize the Host Porting Interface (HPI).
+ */
+HPI::HPI()
+{
+}
+
+void HPI::initialize() // REMOVEME
+{
+       TRACESUBSYSTEMINITIALIZATION("hpi_init");
+
+       // Load libhpi.so
+       VM* vm = VM::get_current();
+       Properties& properties = vm->get_properties();
+       const char* boot_library_path = properties.get("sun.boot.library.path");
+
+       size_t len =
+               os::strlen(boot_library_path) +
+               os::strlen("/native_threads/libhpi.so") +
+               os::strlen("0");
+
+       char* p = MNEW(char, len);
+
+       os::strcpy(p, boot_library_path);
+       os::strcat(p, "/native_threads/libhpi.so");
+
+       utf* u = utf_new_char(p);
+
+    if (opt_TraceHPI)
+               log_println("HPI::initialize: Loading HPI %s ", p);
+
+       MFREE(p, char, len);
+
+       NativeLibrary nl(u);
+       void* handle = nl.open();
+
+       if (handle == NULL)
+               if (opt_TraceHPI)
+                       os::abort("HPI::initialize: HPI open failed");
+
+       // Resolve the DLL_Initialize function from the library.
+       void* dll_initialize = os::dlsym(handle, "DLL_Initialize");
+
+    jint (JNICALL *DLL_Initialize)(GetInterfaceFunc*, void*);
+    DLL_Initialize = (jint (JNICALL *)(GetInterfaceFunc*, void*)) (uintptr_t) dll_initialize;
+
+    if (opt_TraceHPI && DLL_Initialize == NULL)
+               log_println("hpi_init: HPI dlsym of DLL_Initialize failed: %s", os::dlerror());
+
+    if (DLL_Initialize == NULL || (*DLL_Initialize)(&_get_interface, &callbacks) < 0) {
+        if (opt_TraceHPI)
+                       vm_abort("hpi_init: HPI DLL_Initialize failed");
+    }
+
+       NativeLibraries& nls = vm->get_nativelibraries();
+       nls.add(nl);
+
+    if (opt_TraceHPI)
+               log_println("HPI::initialize: HPI loaded successfully");
+
+       // Resolve the interfaces.
+       /* NOTE: The intptr_t-case is only to prevent the a compiler
+          warning with -O2: warning: dereferencing type-punned pointer
+          will break strict-aliasing rules */
+
+       int result;
+
+       result = (*_get_interface)((void**) (uintptr_t) &_file, "File", 1);
+
+       if (result != 0)
+               os::abort("hpi_init: Can't find HPI_FileInterface");
+
+       result = (*_get_interface)((void**) (uintptr_t) &_library, "Library", 1);
+
+       if (result != 0)
+               os::abort("hpi_init: Can't find HPI_LibraryInterface");
+
+       result = (*_get_interface)((void**) (uintptr_t) &_system, "System", 1);
+
+       if (result != 0)
+               os::abort("hpi_init: Can't find HPI_SystemInterface");
+}
+
+
+/**
+ * Initialize the Host Porting Interface (HPI) socket library.
+ */
+int HPI::initialize_socket_library()
+{
+       // Resolve the socket library interface.
+       int result = (*_get_interface)((void**) (uintptr_t) &_socket, "Socket", 1);
+
+       if (result != 0) {
+               if (opt_TraceHPI)
+                       log_println("HPI::initialize_socket_library: Can't find HPI_SocketInterface");
+
+               return JNI_ERR;
+       }
+
+       return JNI_OK;
+}
+
+
+// Legacy C interface.
+extern "C" {
+       void HPI_initialize() { VM::get_current()->get_hpi().initialize(); }
+}
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
diff --git a/src/native/vm/openjdk/hpi.h b/src/native/vm/openjdk/hpi.h
deleted file mode 100644 (file)
index 356b835..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-/* src/native/vm/openjdk/hpi.h - HotSpot HPI interface functions
-
-   Copyright (C) 2008
-   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
-
-   This file is part of CACAO.
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2, or (at
-   your option) any later version.
-
-   This program is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-   02110-1301, USA.
-
-*/
-
-
-#ifndef _HPI_H
-#define _HPI_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "config.h"
-
-/* HPI headers *****************************************************************
-
-   We include hpi_md.h before hpi.h as the latter includes the former.
-
-   These includes define:
-
-   #define _JAVASOFT_HPI_MD_H_
-   #define _JAVASOFT_HPI_H_
-
-*******************************************************************************/
-
-#include INCLUDE_HPI_MD_H
-#include INCLUDE_HPI_H
-
-
-/* HPI interfaces *************************************************************/
-
-extern HPI_FileInterface    *hpi_file;
-extern HPI_SocketInterface  *hpi_socket;
-extern HPI_LibraryInterface *hpi_library;
-extern HPI_SystemInterface  *hpi_system;
-
-
-/* functions ******************************************************************/
-
-void hpi_initialize(void);
-int  hpi_initialize_socket_library(void);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _HPI_H */
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
diff --git a/src/native/vm/openjdk/hpi.hpp b/src/native/vm/openjdk/hpi.hpp
new file mode 100644 (file)
index 0000000..3b09bf2
--- /dev/null
@@ -0,0 +1,97 @@
+/* src/native/vm/openjdk/hpi.hpp - HotSpot HPI interface functions
+
+   Copyright (C) 2008
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+   This file is part of CACAO.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+*/
+
+
+#ifndef _HPI_HPP
+#define _HPI_HPP
+
+#include "config.h"
+
+/* HPI headers *****************************************************************
+
+   We include hpi_md.h before hpi.h as the latter includes the former.
+
+   These includes define:
+
+   #define _JAVASOFT_HPI_MD_H_
+   #define _JAVASOFT_HPI_H_
+
+*******************************************************************************/
+
+// Include our JNI header before the HPI headers, because the HPI
+// headers include jni.h and we want to override the typedefs in
+// jni.h.
+#include "native/jni.hpp"
+
+#include INCLUDE_HPI_MD_H
+#include INCLUDE_HPI_H
+
+
+#ifdef __cplusplus
+
+/**
+ * Host Porting Interface (HPI).
+ */
+class HPI {
+private:
+       GetInterfaceFunc      _get_interface;
+       HPI_FileInterface*    _file;
+       HPI_SocketInterface*  _socket;
+       HPI_LibraryInterface* _library;
+       HPI_SystemInterface*  _system;
+
+public:        
+       HPI();
+
+       inline HPI_FileInterface&    get_file   () const { return *_file; }
+       inline HPI_SocketInterface&  get_socket () const { return *_socket; }
+       inline HPI_LibraryInterface& get_library() const { return *_library; }
+       inline HPI_SystemInterface&  get_system () const { return *_system; }
+       
+       void initialize(); // REMOVEME
+       int initialize_socket_library();
+};
+
+#else
+
+void HPI_initialize();
+
+#endif
+
+#endif // _HPI_HPP
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
index 8a7a1d768d8a80b3124c725e1dfe34eebd1303fe..d23997e8144bc1e0c7a96ffa9635b3471d901fa3 100644 (file)
 #include <sys/stat.h>
 #include <sys/types.h>
 
-#include "vm/types.h"
+// Include our JNI header before the JVM headers, because the JVM
+// headers include jni.h and we want to override the typedefs in
+// jni.h.
+#include "native/jni.hpp"
+
+// We include jvm_md.h before jvm.h as the latter includes the former.
+#include INCLUDE_JVM_MD_H
+#include INCLUDE_JVM_H
 
 #include "mm/memory.h"
 
-#include "native/jni.h"
 #include "native/llni.h"
-#include "native/native.h"
+#include "native/native.hpp"
 
 #include "native/vm/reflection.hpp"
 
-#include "native/vm/openjdk/hpi.h"
+#include "native/vm/openjdk/hpi.hpp"
+#include "native/vm/openjdk/management.hpp"
 
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
 #include "threads/thread.hpp"
 
 #include "toolbox/logging.h"
-#include "toolbox/list.h"
+#include "toolbox/list.hpp"
 
-#include "vm/array.h"
+#include "vm/array.hpp"
 
 #if defined(ENABLE_ASSERTION)
-#include "vm/assertion.h"
+#include "vm/assertion.hpp"
 #endif
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/classcache.h"
 #include "vm/exceptions.hpp"
 #include "vm/global.h"
@@ -76,7 +83,7 @@
 #include "vm/os.hpp"
 #include "vm/package.hpp"
 #include "vm/primitive.hpp"
-#include "vm/properties.h"
+#include "vm/properties.hpp"
 #include "vm/resolve.h"
 #include "vm/signallocal.h"
 #include "vm/string.hpp"
 #endif
 
 
-typedef struct {
-    /* Naming convention of RE build version string: n.n.n[_uu[c]][-<identifier>]-bxx */
-    unsigned int jvm_version;   /* Consists of major, minor, micro (n.n.n) */
-                                /* and build number (xx) */
-    unsigned int update_version : 8;         /* Update release version (uu) */
-    unsigned int special_update_version : 8; /* Special update release version (c) */
-    unsigned int reserved1 : 16; 
-    unsigned int reserved2; 
-
-    /* The following bits represents JVM supports that JDK has dependency on.
-     * JDK can use these bits to determine which JVM version
-     * and support it has to maintain runtime compatibility.
-     *
-     * When a new bit is added in a minor or update release, make sure
-     * the new bit is also added in the main/baseline.
-     */
-    unsigned int is_attachable : 1;
-    unsigned int : 31;
-    unsigned int : 32;
-    unsigned int : 32;
-} jvm_version_info;
-
-
-/*
- * A structure used to a capture exception table entry in a Java method.
- */
-typedef struct {
-    jint start_pc;
-    jint end_pc;
-    jint handler_pc;
-    jint catchType;
-} JVM_ExceptionTableEntryType;
-
-
 // Interface functions are exported as C functions.
 extern "C" {
 
@@ -285,11 +258,10 @@ jobject JVM_InitProperties(JNIEnv *env, jobject properties)
           -D option, as requested. */
 
        jio_snprintf(buf, sizeof(buf), PRINTF_FORMAT_INT64_T, opt_MaxDirectMemorySize);
-       properties_add("sun.nio.MaxDirectMemorySize", buf);
-
-       /* Add all properties. */
+       VM::get_current()->get_properties().put("sun.nio.MaxDirectMemorySize", buf);
 
-       properties_system_add_all(h);
+       // Fill the java.util.Properties object.
+       VM::get_current()->get_properties().fill(h);
 
        return properties;
 }
@@ -503,10 +475,9 @@ jobject JVM_GetStackTraceElement(JNIEnv *env, jobject throwable, jint index)
                linenumber = -2;
        }
        else {
-               /* FIXME The linenumbertable_linenumber_for_pc could change
-                  the methodinfo pointer when hitting an inlined method. */
-
-               linenumber = linenumbertable_linenumber_for_pc(&m, code, ste->pc);
+               // FIXME linenumbertable->find could change the methodinfo
+               // pointer when hitting an inlined method.
+               linenumber = code->linenumbertable->find(&m, ste->pc);
                linenumber = (linenumber == 0) ? -1 : linenumber;
        }
 
@@ -531,7 +502,9 @@ jint JVM_IHashCode(JNIEnv* env, jobject handle)
 {
        TRACEJVMCALLS(("JVM_IHashCode(env=%p, jobject=%p)", env, handle));
 
-       return (jint) ((ptrint) handle);
+       java_lang_Object o(handle);
+
+       return o.get_hashcode();
 }
 
 
@@ -672,21 +645,23 @@ void JVM_DisableCompiler(JNIEnv *env, jclass compCls)
 
 /* JVM_GetLastErrorString */
 
-jint JVM_GetLastErrorString(char *buf, int len)
+jint JVM_GetLastErrorString(charbuf, int len)
 {
        TRACEJVMCALLS(("JVM_GetLastErrorString(buf=%p, len=%d", buf, len));
 
-       return hpi_system->GetLastErrorString(buf, len);
+       HPI& hpi = VM::get_current()->get_hpi();
+       return hpi.get_system().GetLastErrorString(buf, len);
 }
 
 
 /* JVM_NativePath */
 
-char *JVM_NativePath(char *path)
+char *JVM_NativePath(charpath)
 {
        TRACEJVMCALLS(("JVM_NativePath(path=%s)", path));
 
-       return hpi_file->NativePath(path);
+       HPI& hpi = VM::get_current()->get_hpi();
+       return hpi.get_file().NativePath(path);
 }
 
 
@@ -1657,7 +1632,6 @@ jstring JVM_ConstantPoolGetUTF8At(JNIEnv *env, jobject unused, jobject jcpool, j
 jboolean JVM_DesiredAssertionStatus(JNIEnv *env, jclass unused, jclass cls)
 {
 #if defined(ENABLE_ASSERTION)
-       assertion_name_t  *item;
        classinfo         *c;
        jboolean           status;
        utf               *name;
@@ -1674,8 +1648,10 @@ jboolean JVM_DesiredAssertionStatus(JNIEnv *env, jclass unused, jclass cls)
        }
 
        if (list_assertion_names != NULL) {
-               item = (assertion_name_t *)list_first(list_assertion_names);
-               while (item != NULL) {
+               for (List<assertion_name_t*>::iterator it = list_assertion_names->begin();
+                        it != list_assertion_names->end(); it++) {
+                       assertion_name_t* item = *it;
+
                        name = utf_new_char(item->name);
                        if (name == c->packagename) {
                                status = (jboolean)item->enabled;
@@ -1683,8 +1659,6 @@ jboolean JVM_DesiredAssertionStatus(JNIEnv *env, jclass unused, jclass cls)
                        else if (name == c->name) {
                                status = (jboolean)item->enabled;
                        }
-
-                       item = (assertion_name_t *)list_next(list_assertion_names, item);
                }
        }
 
@@ -1704,7 +1678,6 @@ jobject JVM_AssertionStatusDirectives(JNIEnv *env, jclass unused)
        java_booleanarray_t                   *classEnabled;
        java_booleanarray_t                   *packageEnabled;
 #if defined(ENABLE_ASSERTION)
-       assertion_name_t                      *item;
        java_handle_t                         *js;
        s4                                     i, j;
 #endif
@@ -1750,8 +1723,9 @@ jobject JVM_AssertionStatusDirectives(JNIEnv *env, jclass unused)
                i = 0;
                j = 0;
                
-               item = (assertion_name_t *)list_first(list_assertion_names);
-               while (item != NULL) {
+               for (List<assertion_name_t*>::iterator it = list_assertion_names->begin(); it != list_assertion_names->end(); it++) {
+                       assertion_name_t* item = *it;
+
                        js = javastring_new_from_ascii(item->name);
                        if (js == NULL) {
                                return NULL;
@@ -1767,8 +1741,6 @@ jobject JVM_AssertionStatusDirectives(JNIEnv *env, jclass unused)
                                packageEnabled->data[j] = (jboolean) item->enabled;
                                j += 1;
                        }
-
-                       item = (assertion_name_t *)list_next(list_assertion_names, item);
                }
        }
 #endif
@@ -2080,13 +2052,14 @@ jboolean JVM_IsSameClassPackage(JNIEnv *env, jclass class1, jclass class2)
  */
 #define JVM_EEXIST       -100
 
-jint JVM_Open(const char *fname, jint flags, jint mode)
+jint JVM_Open(const charfname, jint flags, jint mode)
 {
        int result;
 
        TRACEJVMCALLS(("JVM_Open(fname=%s, flags=%d, mode=%d)", fname, flags, mode));
 
-       result = hpi_file->Open(fname, flags, mode);
+       HPI& hpi = VM::get_current()->get_hpi();
+       result = hpi.get_file().Open(fname, flags, mode);
 
        if (result >= 0) {
                return result;
@@ -2108,37 +2081,41 @@ jint JVM_Close(jint fd)
 {
        TRACEJVMCALLS(("JVM_Close(fd=%d)", fd));
 
-       return hpi_file->Close(fd);
+       HPI& hpi = VM::get_current()->get_hpi();
+       return hpi.get_file().Close(fd);
 }
 
 
 /* JVM_Read */
 
-jint JVM_Read(jint fd, char *buf, jint nbytes)
+jint JVM_Read(jint fd, charbuf, jint nbytes)
 {
        TRACEJVMCALLS(("JVM_Read(fd=%d, buf=%p, nbytes=%d)", fd, buf, nbytes));
 
-       return (jint) hpi_file->Read(fd, buf, nbytes);
+       HPI& hpi = VM::get_current()->get_hpi();
+       return (jint) hpi.get_file().Read(fd, buf, nbytes);
 }
 
 
 /* JVM_Write */
 
-jint JVM_Write(jint fd, char *buf, jint nbytes)
+jint JVM_Write(jint fd, charbuf, jint nbytes)
 {
        TRACEJVMCALLS(("JVM_Write(fd=%d, buf=%s, nbytes=%d)", fd, buf, nbytes));
 
-       return (jint) hpi_file->Write(fd, buf, nbytes);
+       HPI& hpi = VM::get_current()->get_hpi();
+       return (jint) hpi.get_file().Write(fd, buf, nbytes);
 }
 
 
 /* JVM_Available */
 
-jint JVM_Available(jint fd, jlong *pbytes)
+jint JVM_Available(jint fd, jlongpbytes)
 {
        TRACEJVMCALLS(("JVM_Available(fd=%d, pbytes=%p)", fd, pbytes));
 
-       return hpi_file->Available(fd, pbytes);
+       HPI& hpi = VM::get_current()->get_hpi();
+       return hpi.get_file().Available(fd, pbytes);
 }
 
 
@@ -2148,7 +2125,8 @@ jlong JVM_Lseek(jint fd, jlong offset, jint whence)
 {
        TRACEJVMCALLS(("JVM_Lseek(fd=%d, offset=%ld, whence=%d)", fd, offset, whence));
 
-       return hpi_file->Seek(fd, (off_t) offset, whence);
+       HPI& hpi = VM::get_current()->get_hpi();
+       return hpi.get_file().Seek(fd, (off_t) offset, whence);
 }
 
 
@@ -2158,7 +2136,8 @@ jint JVM_SetLength(jint fd, jlong length)
 {
        TRACEJVMCALLS(("JVM_SetLength(fd=%d, length=%ld)", length));
 
-       return hpi_file->SetLength(fd, length);
+       HPI& hpi = VM::get_current()->get_hpi();
+       return hpi.get_file().SetLength(fd, length);
 }
 
 
@@ -2168,7 +2147,8 @@ jint JVM_Sync(jint fd)
 {
        TRACEJVMCALLS(("JVM_Sync(fd=%d)", fd));
 
-       return hpi_file->Sync(fd);
+       HPI& hpi = VM::get_current()->get_hpi();
+       return hpi.get_file().Sync(fd);
 }
 
 
@@ -2688,7 +2668,8 @@ jint JVM_InitializeSocketLibrary()
 {
        TRACEJVMCALLS(("JVM_InitializeSocketLibrary()"));
 
-       return hpi_initialize_socket_library();
+       HPI& hpi = VM::get_current()->get_hpi();
+       return hpi.initialize_socket_library();
 }
 
 
@@ -2916,17 +2897,15 @@ struct protoent *JVM_GetProtoByName(char* name)
 
 /* JVM_LoadLibrary */
 
-void *JVM_LoadLibrary(const char *name)
+void* JVM_LoadLibrary(const char* name)
 {
-       utf*  u;
-       void* handle;
-
        TRACEJVMCALLSENTER(("JVM_LoadLibrary(name=%s)", name));
 
-       u = utf_new_char(name);
-
-       handle = native_library_open(u);
+       utf* u = utf_new_char(name);
 
+       NativeLibrary nl(u);
+       void* handle = nl.open();
+       
        TRACEJVMCALLSEXIT(("->%p", handle));
 
        return handle;
@@ -2939,19 +2918,21 @@ void JVM_UnloadLibrary(void* handle)
 {
        TRACEJVMCALLS(("JVM_UnloadLibrary(handle=%p)", handle));
 
-       native_library_close(handle);
+       NativeLibrary nl(handle);
+       nl.close();
 }
 
 
 /* JVM_FindLibraryEntry */
 
-void *JVM_FindLibraryEntry(void *handle, const char *name)
+void *JVM_FindLibraryEntry(void* handle, const char* name)
 {
        void* symbol;
 
        TRACEJVMCALLSENTER(("JVM_FindLibraryEntry(handle=%p, name=%s)", handle, name));
 
-       symbol = hpi_library->FindLibraryEntry(handle, name);
+       HPI& hpi = VM::get_current()->get_hpi();
+       symbol = hpi.get_library().FindLibraryEntry(handle, name);
 
        TRACEJVMCALLSEXIT(("->%p", symbol));
 
@@ -2993,35 +2974,31 @@ jstring JVM_InternString(JNIEnv *env, jstring str)
 
 JNIEXPORT void* JNICALL JVM_RawMonitorCreate(void)
 {
-       java_object_t *o;
-
        TRACEJVMCALLS(("JVM_RawMonitorCreate()"));
 
-       o = NEW(java_object_t);
-
-       lock_init_object_lock(o);
+       Mutex* m = new Mutex();
 
-       return o;
+       return m;
 }
 
 
 /* JVM_RawMonitorDestroy */
 
-JNIEXPORT void JNICALL JVM_RawMonitorDestroy(void *mon)
+JNIEXPORT void JNICALL JVM_RawMonitorDestroy(voidmon)
 {
        TRACEJVMCALLS(("JVM_RawMonitorDestroy(mon=%p)", mon));
 
-       FREE(mon, java_object_t);
+       delete ((Mutex*) mon);
 }
 
 
 /* JVM_RawMonitorEnter */
 
-JNIEXPORT jint JNICALL JVM_RawMonitorEnter(void *mon)
+JNIEXPORT jint JNICALL JVM_RawMonitorEnter(voidmon)
 {
        TRACEJVMCALLS(("JVM_RawMonitorEnter(mon=%p)", mon));
 
-       (void) lock_monitor_enter((java_object_t *) mon);
+       ((Mutex*) mon)->lock();
 
        return 0;
 }
@@ -3029,11 +3006,11 @@ JNIEXPORT jint JNICALL JVM_RawMonitorEnter(void *mon)
 
 /* JVM_RawMonitorExit */
 
-JNIEXPORT void JNICALL JVM_RawMonitorExit(void *mon)
+JNIEXPORT void JNICALL JVM_RawMonitorExit(voidmon)
 {
        TRACEJVMCALLS(("JVM_RawMonitorExit(mon=%p)", mon));
 
-       (void) lock_monitor_exit((java_object_t *) mon);
+       ((Mutex*) mon)->unlock();
 }
 
 
@@ -3266,9 +3243,7 @@ void *JVM_GetManagement(jint version)
 {
        TRACEJVMCALLS(("JVM_GetManagement(version=%d)", version));
 
-       /* TODO We current don't support the management interface. */
-
-       return NULL;
+       return Management::get_jmm_interface(version);
 }
 
 
@@ -3632,4 +3607,5 @@ jint JVM_FindSignal(const char *name)
  * c-basic-offset: 4
  * tab-width: 4
  * End:
+ * vim:noexpandtab:sw=4:ts=4:
  */
diff --git a/src/native/vm/openjdk/management.cpp b/src/native/vm/openjdk/management.cpp
new file mode 100644 (file)
index 0000000..3884893
--- /dev/null
@@ -0,0 +1,377 @@
+ /* src/native/vm/openjdk/management.cpp - HotSpot management interface functions
+
+   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 our JNI header before the JMM header, because the JMM
+// header include jni.h and we want to override the typedefs in jni.h.
+#include "native/jni.hpp"
+
+#include INCLUDE_JMM_H
+
+#include "native/vm/openjdk/management.hpp"
+
+#include "toolbox/logging.h"
+
+#include "vm/os.hpp"
+#include "vm/vm.hpp"
+
+
+/**
+ * Initialize the Management subsystem.
+ */
+Management::Management()
+{
+       // Initialize optional support
+       _optional_support.isLowMemoryDetectionSupported = 1;
+       _optional_support.isCompilationTimeMonitoringSupported = 1;
+       _optional_support.isThreadContentionMonitoringSupported = 1;
+
+//     if (os::is_thread_cpu_time_supported()) {
+       if (false) {
+               _optional_support.isCurrentThreadCpuTimeSupported = 1;
+               _optional_support.isOtherThreadCpuTimeSupported = 1;
+       }
+       else {
+               _optional_support.isCurrentThreadCpuTimeSupported = 0;
+               _optional_support.isOtherThreadCpuTimeSupported = 0;
+       }
+
+       _optional_support.isBootClassPathSupported = 1;
+       _optional_support.isObjectMonitorUsageSupported = 1;
+       _optional_support.isSynchronizerUsageSupported = 1;
+}
+
+
+/**
+ * Return a pointer to the optional support structure.
+ *
+ * @param Pointer to optional support structure.
+ */
+const jmmOptionalSupport& Management::get_optional_support() const
+{
+       return _optional_support;
+}
+
+
+// Interface functions are exported as C functions.
+extern "C" {
+
+// Returns a version string and sets major and minor version if the
+// input parameters are non-null.
+jint jmm_GetVersion(JNIEnv* env)
+{
+       return JMM_VERSION;
+}
+
+
+// Gets the list of VM monitoring and management optional supports
+// Returns 0 if succeeded; otherwise returns non-zero.
+jint jmm_GetOptionalSupport(JNIEnv* env, jmmOptionalSupport* support)
+{
+       if (support == NULL) {
+               return -1;
+       }
+
+       Management& mm = VM::get_current()->get_management();
+
+       // memcpy the structure.
+       os::memcpy(support, &mm.get_optional_support(), sizeof(jmmOptionalSupport));
+
+       return 0;
+}
+
+
+jobject jmm_GetInputArguments(JNIEnv* env)
+{
+       log_println("jmm_GetInputArguments: IMPLEMENT ME!");
+       return NULL;
+}
+
+
+jobjectArray jmm_GetInputArgumentArray(JNIEnv* env)
+{
+       log_println("jmm_GetInputArgumentArray: IMPLEMENT ME!");
+       return NULL;
+}
+
+
+jobjectArray jmm_GetMemoryPools(JNIEnv* env, jobject obj)
+{
+       log_println("jmm_GetMemoryPools: IMPLEMENT ME!");
+       return NULL;
+}
+
+
+jobjectArray jmm_GetMemoryManagers(JNIEnv* env, jobject obj)
+{
+       log_println("jmm_GetMemoryManagers: IMPLEMENT ME!");
+       return NULL;
+}
+
+
+jobject jmm_GetMemoryPoolUsage(JNIEnv* env, jobject obj)
+{
+       log_println("jmm_GetMemoryPoolUsage: IMPLEMENT ME!");
+       return NULL;
+}
+
+
+jobject jmm_GetPeakMemoryPoolUsage(JNIEnv* env, jobject obj)
+{
+       log_println("jmm_GetPeakMemoryPoolUsage: IMPLEMENT ME!");
+       return NULL;
+}
+
+
+jobject jmm_GetPoolCollectionUsage(JNIEnv* env, jobject obj)
+{
+       log_println("jmm_GetPoolCollectionUsage: IMPLEMENT ME!");
+       return NULL;
+}
+
+
+void jmm_SetPoolSensor(JNIEnv* env, jobject obj, jmmThresholdType type, jobject sensorObj)
+{
+       log_println("jmm_SetPoolSensor: IMPLEMENT ME!");
+}
+
+
+jlong jmm_SetPoolThreshold(JNIEnv* env, jobject obj, jmmThresholdType type, jlong threshold)
+{
+       log_println("jmm_SetPoolThreshold: IMPLEMENT ME!");
+       return 0;
+}
+
+
+jobject jmm_GetMemoryUsage(JNIEnv* env, jboolean heap)
+{
+       log_println("jmm_GetMemoryUsage: IMPLEMENT ME!");
+       return NULL;
+}
+
+
+jboolean jmm_GetBoolAttribute(JNIEnv* env, jmmBoolAttribute att)
+{
+       log_println("jmm_GetBoolAttribute: IMPLEMENT ME!");
+       return 0;
+}
+
+
+jboolean jmm_SetBoolAttribute(JNIEnv* env, jmmBoolAttribute att, jboolean flag)
+{
+       log_println("jmm_SetBoolAttribute: IMPLEMENT ME!");
+       return 0;
+}
+
+
+jlong jmm_GetLongAttribute(JNIEnv* env, jobject obj, jmmLongAttribute att)
+{
+       log_println("jmm_GetLongAttribute: IMPLEMENT ME!");
+       return 0;
+}
+
+
+jint jmm_GetLongAttributes(JNIEnv* env, jobject obj, jmmLongAttribute* atts, jint count, jlong* result)
+{
+       log_println("jmm_GetLongAttributes: IMPLEMENT ME!");
+       return 0;
+}
+
+
+jint jmm_GetThreadInfo(JNIEnv* env, jlongArray ids, jint maxDepth, jobjectArray infoArray)
+{
+       log_println("jmm_GetThreadInfo: IMPLEMENT ME!");
+       return 0;
+}
+
+
+jobjectArray jmm_DumpThreads(JNIEnv* env, jlongArray thread_ids, jboolean locked_monitors, jboolean locked_synchronizers)
+{
+       log_println("jmm_DumpThreads: IMPLEMENT ME!");
+       return NULL;
+}
+
+
+jobjectArray jmm_GetLoadedClasses(JNIEnv* env)
+{
+       log_println("jmm_GetLoadedClasses: IMPLEMENT ME!");
+       return NULL;
+}
+
+
+jboolean jmm_ResetStatistic(JNIEnv* env, jvalue obj, jmmStatisticType type)
+{
+       log_println("jmm_ResetStatistic: IMPLEMENT ME!");
+       return 0;
+}
+
+
+jlong jmm_GetThreadCpuTime(JNIEnv* env, jlong thread_id)
+{
+       log_println("jmm_GetThreadCpuTime: IMPLEMENT ME!");
+       return 0;
+}
+
+
+jlong jmm_GetThreadCpuTimeWithKind(JNIEnv* env, jlong thread_id, jboolean user_sys_cpu_time)
+{
+       log_println("jmm_GetThreadCpuTimeWithKind: IMPLEMENT ME!");
+       return 0;
+}
+
+
+jobjectArray jmm_GetVMGlobalNames(JNIEnv* env)
+{
+       log_println("jmm_GetVMGlobalNames: IMPLEMENT ME!");
+       return NULL;
+}
+
+
+jint jmm_GetVMGlobals(JNIEnv* env, jobjectArray names, jmmVMGlobal* globals, jint count)
+{
+       log_println("jmm_GetVMGlobals: IMPLEMENT ME!");
+       return 0;
+}
+
+
+void jmm_SetVMGlobal(JNIEnv* env, jstring flag_name, jvalue new_value)
+{
+       log_println("jmm_SetVMGlobal: IMPLEMENT ME!");
+}
+
+
+jint jmm_GetInternalThreadTimes(JNIEnv* env, jobjectArray names, jlongArray times)
+{
+       log_println("jmm_GetInternalThreadTimes: IMPLEMENT ME!");
+       return 0;
+}
+
+
+jobjectArray jmm_FindDeadlockedThreads(JNIEnv* env, jboolean object_monitors_only)
+{
+       log_println("jmm_FindDeadlockedThreads: IMPLEMENT ME!");
+       return NULL;
+}
+
+
+jobjectArray jmm_FindMonitorDeadlockedThreads(JNIEnv* env)
+{
+       log_println("jmm_FindMonitorDeadlockedThreads: IMPLEMENT ME!");
+       return NULL;
+}
+
+
+jint jmm_GetGCExtAttributeInfo(JNIEnv* env, jobject mgr, jmmExtAttributeInfo* info, jint count)
+{
+       log_println("jmm_GetGCExtAttributeInfo: IMPLEMENT ME!");
+       return 0;
+}
+
+
+void jmm_GetLastGCStat(JNIEnv* env, jobject obj, jmmGCStat* gc_stat)
+{
+       log_println("jmm_GetLastGCStat: IMPLEMENT ME!");
+}
+
+
+jint jmm_DumpHeap0(JNIEnv* env, jstring outputfile, jboolean live)
+{
+       log_println("jmm_DumpHeap0: IMPLEMENT ME!");
+       return 0;
+}
+
+} // extern "C"
+
+
+const struct jmmInterface_1_ jmm_interface = {
+       NULL,
+       NULL,
+       jmm_GetVersion,
+       jmm_GetOptionalSupport,
+       jmm_GetInputArguments,
+       jmm_GetThreadInfo,
+       jmm_GetInputArgumentArray,
+       jmm_GetMemoryPools,
+       jmm_GetMemoryManagers,
+       jmm_GetMemoryPoolUsage,
+       jmm_GetPeakMemoryPoolUsage,
+       NULL,
+       jmm_GetMemoryUsage,
+       jmm_GetLongAttribute,
+       jmm_GetBoolAttribute,
+       jmm_SetBoolAttribute,
+       jmm_GetLongAttributes,
+       jmm_FindMonitorDeadlockedThreads,
+       jmm_GetThreadCpuTime,
+       jmm_GetVMGlobalNames,
+       jmm_GetVMGlobals,
+       jmm_GetInternalThreadTimes,
+       jmm_ResetStatistic,
+       jmm_SetPoolSensor,
+       jmm_SetPoolThreshold,
+       jmm_GetPoolCollectionUsage,
+       jmm_GetGCExtAttributeInfo,
+       jmm_GetLastGCStat,
+       jmm_GetThreadCpuTimeWithKind,
+       NULL,
+       jmm_DumpHeap0,
+       jmm_FindDeadlockedThreads,
+       jmm_SetVMGlobal,
+       NULL,
+       jmm_DumpThreads
+};
+
+
+/**
+ * Return the requested management interface.
+ *
+ * @param version Requested management interface version.
+ *
+ * @return Pointer to management interface structure.
+ */
+void* Management::get_jmm_interface(int version)
+{
+       if (version == JMM_VERSION_1_0) {
+               return (void*) &jmm_interface;
+       }
+
+       return NULL;
+}
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
diff --git a/src/native/vm/openjdk/management.hpp b/src/native/vm/openjdk/management.hpp
new file mode 100644 (file)
index 0000000..4c83d88
--- /dev/null
@@ -0,0 +1,75 @@
+/* src/native/vm/openjdk/management.hpp - HotSpot management interface functions
+
+   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 _MANAGEMENT_HPP
+#define _MANAGEMENT_HPP
+
+#include <stdint.h>
+
+// Include our JNI header before the JMM header, because the JMM
+// header include jni.h and we want to override the typedefs in jni.h.
+#include "native/jni.hpp"
+
+#include INCLUDE_JMM_H
+
+
+#ifdef __cplusplus
+
+/**
+ * Management support.
+ */
+class Management {
+private:
+       jmmOptionalSupport _optional_support;
+
+public:
+       Management();
+
+       static void* get_jmm_interface(int version);
+
+       const jmmOptionalSupport& get_optional_support() const;
+};
+
+#else
+
+typedef struct Management Management;
+
+#endif
+
+#endif // _MANAGEMENT_HPP
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
index 421467f41ef9a5522358d68901be651c15825474..48c181a3fb226afadacc28a692056173a0bf26fe 100644 (file)
@@ -27,9 +27,8 @@
 
 #include <stdint.h>
 
-#include "native/jni.h"
 #include "native/llni.h"
-#include "native/native.h"
+#include "native/native.hpp"
 
 #if defined(ENABLE_ANNOTATIONS) && defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
 # include "vm/vm.hpp"
@@ -38,7 +37,7 @@
 #include "native/vm/reflection.hpp"
 
 #include "vm/access.h"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/exceptions.hpp"
 #include "vm/global.h"
 #include "vm/globals.hpp"
index 39418abe7e12841f1ff5aced322a312770288689..c4fe674e261db912eded548e089f848ebdd172d0 100644 (file)
 
 #include <stdint.h>
 
-#include "native/jni.h"
-#include "native/native.h"
+#include "native/native.hpp"
 
-#include "vm/field.h"
+#include "vm/field.hpp"
 #include "vm/method.h"
 
 
index 4544393129cad6fce8386bc8de0dda763fe61e4f..439afc2cd3b5818cbcbdd986333c385ebef6b7aa 100644 (file)
 
 #include "mm/memory.h"
 
-#include "native/jni.h"
+#include "native/jni.hpp"
 #include "native/llni.h"
-#include "native/native.h"
+#include "native/native.hpp"
 
 #if defined(ENABLE_JNI_HEADERS)
 # include "native/include/sun_misc_Unsafe.h"
 #endif
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/exceptions.hpp"
 #include "vm/initialize.h"
 #include "vm/javaobjects.hpp"
@@ -72,14 +72,7 @@ JNIEXPORT void JNICALL Java_sun_misc_Unsafe_registerNatives(JNIEnv *env, jclass
  */
 JNIEXPORT jint JNICALL Java_sun_misc_Unsafe_getInt__Ljava_lang_Object_2J(JNIEnv *env, jobject _this, jobject o, jlong offset)
 {
-       int32_t *p;
-       int32_t  value;
-
-       p = (int32_t *) (((uint8_t *) o) + offset);
-
-       value = *p;
-
-       return value;
+       return FieldAccess::get<int32_t>(o, offset);
 }
 
 
@@ -90,11 +83,7 @@ JNIEXPORT jint JNICALL Java_sun_misc_Unsafe_getInt__Ljava_lang_Object_2J(JNIEnv
  */
 JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putInt__Ljava_lang_Object_2JI(JNIEnv *env, jobject _this, jobject o, jlong offset, jint x)
 {
-       int32_t *p;
-
-       p = (int32_t *) (((uint8_t *) o) + offset);
-
-       *p = x;
+       FieldAccess::set(o, offset, x);
 }
 
 
@@ -105,14 +94,7 @@ JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putInt__Ljava_lang_Object_2JI(JNIEnv
  */
 JNIEXPORT jobject JNICALL Java_sun_misc_Unsafe_getObject(JNIEnv *env, jobject _this, jobject o, jlong offset)
 {
-       void **p;
-       void  *value;
-
-       p = (void **) (((uint8_t *) o) + offset);
-
-       value = *p;
-
-       return (jobject) value;
+       return FieldAccess::get<jobject>(o, offset);
 }
 
 
@@ -123,11 +105,7 @@ JNIEXPORT jobject JNICALL Java_sun_misc_Unsafe_getObject(JNIEnv *env, jobject _t
  */
 JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putObject(JNIEnv *env, jobject _this, jobject o, jlong offset, jobject x)
 {
-       void **p;
-
-       p = (void **) (((uint8_t *) o) + offset);
-
-       *p = (void *) x;
+       FieldAccess::set(o, offset, x);
 }
 
 
@@ -138,14 +116,7 @@ JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putObject(JNIEnv *env, jobject _this
  */
 JNIEXPORT jboolean JNICALL Java_sun_misc_Unsafe_getBoolean(JNIEnv *env, jobject _this, jobject o, jlong offset)
 {
-       int32_t *p;
-       int32_t  value;
-
-       p = (int32_t *) (((uint8_t *) o) + offset);
-
-       value = *p;
-
-       return value;
+       return FieldAccess::get<int32_t>(o, offset);
 }
 
 
@@ -156,11 +127,7 @@ JNIEXPORT jboolean JNICALL Java_sun_misc_Unsafe_getBoolean(JNIEnv *env, jobject
  */
 JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putBoolean(JNIEnv *env, jobject _this, jobject o, jlong offset, jboolean x)
 {
-       int32_t *p;
-
-       p = (int32_t *) (((uint8_t *) o) + offset);
-
-       *p = x;
+       FieldAccess::set(o, offset, (int32_t) x);
 }
 
 
@@ -171,14 +138,7 @@ JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putBoolean(JNIEnv *env, jobject _thi
  */
 JNIEXPORT jbyte JNICALL Java_sun_misc_Unsafe_getByte__Ljava_lang_Object_2J(JNIEnv *env, jobject _this, jobject o, jlong offset)
 {
-       int32_t *p;
-       int32_t  value;
-
-       p = (int32_t *) (((uint8_t *) o) + offset);
-
-       value = *p;
-
-       return value;
+       return FieldAccess::get<int32_t>(o, offset);
 }
 
 
@@ -189,11 +149,7 @@ JNIEXPORT jbyte JNICALL Java_sun_misc_Unsafe_getByte__Ljava_lang_Object_2J(JNIEn
  */
 JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putByte__Ljava_lang_Object_2JB(JNIEnv *env, jobject _this, jobject o, jlong offset, jbyte x)
 {
-       int32_t *p;
-
-       p = (int32_t *) (((uint8_t *) o) + offset);
-
-       *p = x;
+       FieldAccess::set(o, offset, (int32_t) x);
 }
 
 
@@ -204,14 +160,7 @@ JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putByte__Ljava_lang_Object_2JB(JNIEn
  */
 JNIEXPORT jshort JNICALL Java_sun_misc_Unsafe_getShort__Ljava_lang_Object_2J(JNIEnv *env, jobject _this, jobject o, jlong offset)
 {
-       int32_t *p;
-       int32_t  value;
-
-       p = (int32_t *) (((uint8_t *) o) + offset);
-
-       value = *p;
-
-       return value;
+       return FieldAccess::get<int32_t>(o, offset);
 }
 
 
@@ -222,11 +171,7 @@ JNIEXPORT jshort JNICALL Java_sun_misc_Unsafe_getShort__Ljava_lang_Object_2J(JNI
  */
 JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putShort__Ljava_lang_Object_2JS(JNIEnv *env, jobject _this, jobject o, jlong offset, jshort x)
 {
-       int32_t *p;
-
-       p = (int32_t *) (((uint8_t *) o) + offset);
-
-       *p = x;
+       FieldAccess::set(o, offset, (int32_t) x);
 }
 
 
@@ -237,14 +182,7 @@ JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putShort__Ljava_lang_Object_2JS(JNIE
  */
 JNIEXPORT jchar JNICALL Java_sun_misc_Unsafe_getChar__Ljava_lang_Object_2J(JNIEnv *env, jobject _this, jobject o, jlong offset)
 {
-       int32_t *p;
-       int32_t  value;
-
-       p = (int32_t *) (((uint8_t *) o) + offset);
-
-       value = *p;
-
-       return value;
+       return FieldAccess::get<int32_t>(o, offset);
 }
 
 
@@ -255,11 +193,7 @@ JNIEXPORT jchar JNICALL Java_sun_misc_Unsafe_getChar__Ljava_lang_Object_2J(JNIEn
  */
 JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putChar__Ljava_lang_Object_2JC(JNIEnv *env, jobject _this, jobject o, jlong offset, jchar x)
 {
-       int32_t *p;
-
-       p = (int32_t *) (((uint8_t *) o) + offset);
-
-       *p = x;
+       FieldAccess::set(o, offset, (int32_t) x);
 }
 
 
@@ -270,14 +204,7 @@ JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putChar__Ljava_lang_Object_2JC(JNIEn
  */
 JNIEXPORT jlong JNICALL Java_sun_misc_Unsafe_getLong__Ljava_lang_Object_2J(JNIEnv *env, jobject _this, jobject o, jlong offset)
 {
-       int64_t *p;
-       int64_t  value;
-
-       p = (int64_t *) (((uint8_t *) o) + offset);
-
-       value = *p;
-
-       return value;
+       return FieldAccess::get<int64_t>(o, offset);
 }
 
 
@@ -288,11 +215,7 @@ JNIEXPORT jlong JNICALL Java_sun_misc_Unsafe_getLong__Ljava_lang_Object_2J(JNIEn
  */
 JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putLong__Ljava_lang_Object_2JJ(JNIEnv *env, jobject _this, jobject o, jlong offset, jlong x)
 {
-       int64_t *p;
-
-       p = (int64_t *) (((uint8_t *) o) + offset);
-
-       *p = x;
+       FieldAccess::set(o, offset, x);
 }
 
 
@@ -303,14 +226,7 @@ JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putLong__Ljava_lang_Object_2JJ(JNIEn
  */
 JNIEXPORT jfloat JNICALL Java_sun_misc_Unsafe_getFloat__Ljava_lang_Object_2J(JNIEnv *env, jobject _this, jobject o, jlong offset)
 {
-       float *p;
-       float  value;
-
-       p = (float *) (((uint8_t *) o) + offset);
-
-       value = *p;
-
-       return value;
+       return FieldAccess::get<float>(o, offset);
 }
 
 
@@ -321,11 +237,7 @@ JNIEXPORT jfloat JNICALL Java_sun_misc_Unsafe_getFloat__Ljava_lang_Object_2J(JNI
  */
 JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putFloat__Ljava_lang_Object_2JF(JNIEnv *env, jobject _this, jobject o, jlong offset, jfloat x)
 {
-       float *p;
-
-       p = (float *) (((uint8_t *) o) + offset);
-
-       *p = x;
+       FieldAccess::set(o, offset, x);
 }
 
 
@@ -336,14 +248,7 @@ JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putFloat__Ljava_lang_Object_2JF(JNIE
  */
 JNIEXPORT jdouble JNICALL Java_sun_misc_Unsafe_getDouble__Ljava_lang_Object_2J(JNIEnv *env, jobject _this, jobject o, jlong offset)
 {
-       double *p;
-       double  value;
-
-       p = (double *) (((uint8_t *) o) + offset);
-
-       value = *p;
-
-       return value;
+       return FieldAccess::get<double>(o, offset);
 }
 
 
@@ -354,11 +259,7 @@ JNIEXPORT jdouble JNICALL Java_sun_misc_Unsafe_getDouble__Ljava_lang_Object_2J(J
  */
 JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putDouble__Ljava_lang_Object_2JD(JNIEnv *env, jobject _this, jobject o, jlong offset, jdouble x)
 {
-       double *p;
-
-       p = (double *) (((uint8_t *) o) + offset);
-
-       *p = x;
+       FieldAccess::set(o, offset, x);
 }
 
 
@@ -1034,14 +935,7 @@ JNIEXPORT jboolean JNICALL Java_sun_misc_Unsafe_compareAndSwapLong(JNIEnv *env,
  */
 JNIEXPORT jobject JNICALL Java_sun_misc_Unsafe_getObjectVolatile(JNIEnv *env, jobject _this, jobject o, jlong offset)
 {
-       volatile void **p;
-       volatile void  *value;
-
-       p = (volatile void **) (((uint8_t *) o) + offset);
-
-       value = *p;
-
-       return (jobject ) value;
+       return FieldAccess::get_volatile<jobject>(o, offset);
 }
 
 
@@ -1052,51 +946,19 @@ JNIEXPORT jobject JNICALL Java_sun_misc_Unsafe_getObjectVolatile(JNIEnv *env, jo
  */
 JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putObjectVolatile(JNIEnv *env, jobject _this, jobject o, jlong offset, jobject x)
 {
-       volatile void **p;
+       FieldAccess::set_volatile(o, offset, x);
+}
 
-       p = (volatile void **) (((uint8_t *) o) + offset);
 
-       *p = x;
-}
-
-
-#define UNSAFE_GET_VOLATILE(type)                                                      \
-       java_handle_t *_h;                                                                              \
-       java_object_t *_o;                                                                              \
-       volatile type *_p;                                                                              \
-       volatile type  _x;                                                                              \
-                                                                                                                       \
-       _h = (java_handle_t *) o;                                                               \
-                                                                                                                       \
-       LLNI_CRITICAL_START;                                                                    \
-                                                                                                                       \
-       _o = LLNI_UNWRAP(_h);                                                                   \
-       _p = (volatile type *) (((uint8_t *) _o) + offset);             \
-                                                                                                                       \
-       _x = *_p;                                                                                               \
-                                                                                                                       \
-       LLNI_CRITICAL_END;                                                                              \
-                                                                                                                       \
-       return _x;
-
-
-#define UNSAFE_PUT_VOLATILE(type)                                                      \
-       java_handle_t *_h;                                                                              \
-       java_object_t *_o;                                                                              \
-       volatile type *_p;                                                                              \
-                                                                                                                       \
-       _h = (java_handle_t *) o;                                                               \
-                                                                                                                       \
-       LLNI_CRITICAL_START;                                                                    \
-                                                                                                                       \
-       _o = LLNI_UNWRAP(_h);                                                                   \
-       _p = (volatile type *) (((uint8_t *) _o) + offset);             \
-                                                                                                                       \
-       *_p = x;                                                                                                \
-                                                                                                                       \
-       Atomic::memory_barrier();                                                               \
-                                                                                                                       \
-       LLNI_CRITICAL_END;
+/*
+ * Class:     sun/misc/Unsafe
+ * Method:    getByteVolatile
+ * Signature: (Ljava/lang/Object;J)B
+ */
+JNIEXPORT jbyte JNICALL Java_sun_misc_Unsafe_getByteVolatile(JNIEnv* env, jobject _this, jobject o, jlong offset)
+{
+       return FieldAccess::get_volatile<int32_t>(o, offset);
+}
 
 
 /*
@@ -1106,7 +968,7 @@ JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putObjectVolatile(JNIEnv *env, jobje
  */
 JNIEXPORT jint JNICALL Java_sun_misc_Unsafe_getIntVolatile(JNIEnv *env, jobject _this, jobject o, jlong offset)
 {
-       UNSAFE_GET_VOLATILE(int32_t);
+       return FieldAccess::get_volatile<int32_t>(o, offset);
 }
 
 
@@ -1117,7 +979,7 @@ JNIEXPORT jint JNICALL Java_sun_misc_Unsafe_getIntVolatile(JNIEnv *env, jobject
  */
 JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putIntVolatile(JNIEnv *env, jobject _this, jobject o, jlong offset, jint x)
 {
-       UNSAFE_PUT_VOLATILE(int32_t);
+       FieldAccess::set_volatile(o, offset, x);
 }
 
 
@@ -1128,7 +990,7 @@ JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putIntVolatile(JNIEnv *env, jobject
  */
 JNIEXPORT jlong JNICALL Java_sun_misc_Unsafe_getLongVolatile(JNIEnv *env, jobject _this, jobject o, jlong offset)
 {
-       UNSAFE_GET_VOLATILE(int64_t);
+       return FieldAccess::get_volatile<int64_t>(o, offset);
 }
 
 
@@ -1139,7 +1001,18 @@ JNIEXPORT jlong JNICALL Java_sun_misc_Unsafe_getLongVolatile(JNIEnv *env, jobjec
  */
 JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putLongVolatile(JNIEnv *env, jobject _this, jobject o, jlong offset, jlong x)
 {
-       UNSAFE_PUT_VOLATILE(int64_t);
+       FieldAccess::set_volatile(o, offset, x);
+}
+
+
+/*
+ * Class:     sun/misc/Unsafe
+ * Method:    getFloatVolatile
+ * Signature: (Ljava/lang/Object;J)F
+ */
+JNIEXPORT jfloat JNICALL Java_sun_misc_Unsafe_getFloatVolatile(JNIEnv* env, jobject _this, jobject o, jlong offset)
+{
+       return FieldAccess::get_volatile<float>(o, offset);
 }
 
 
@@ -1148,9 +1021,9 @@ JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putLongVolatile(JNIEnv *env, jobject
  * Method:    getDoubleVolatile
  * Signature: (Ljava/lang/Object;J)D
  */
-JNIEXPORT jdouble JNICALL Java_sun_misc_Unsafe_getDoubleVolatile(JNIEnv *env, jobject __this, jobject o, jlong offset)
+JNIEXPORT jdouble JNICALL Java_sun_misc_Unsafe_getDoubleVolatile(JNIEnv *env, jobject _this, jobject o, jlong offset)
 {
-       UNSAFE_GET_VOLATILE(double);
+       return FieldAccess::get_volatile<double>(o, offset);
 }
 
 
@@ -1161,26 +1034,7 @@ JNIEXPORT jdouble JNICALL Java_sun_misc_Unsafe_getDoubleVolatile(JNIEnv *env, jo
  */
 JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putOrderedObject(JNIEnv *env, jobject _this, jobject o, jlong offset, jobject x)
 {
-       java_handle_t  *_h;
-       java_handle_t  *_hx;
-       java_object_t  *_o;
-       java_object_t  *_x;
-       volatile void **_p;
-
-       _h  = (java_handle_t *) o;
-       _hx = (java_handle_t *) x;
-
-       LLNI_CRITICAL_START;
-
-       _o = LLNI_UNWRAP(_h);
-       _x = LLNI_UNWRAP(_hx);
-       _p = (volatile void **) (((uint8_t *) _o) + offset);
-
-       *_p = _x;
-
-       Atomic::memory_barrier();
-
-       LLNI_CRITICAL_END;
+       FieldAccess::set_volatile(o, offset, x);
 }
 
 
@@ -1191,7 +1045,7 @@ JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putOrderedObject(JNIEnv *env, jobjec
  */
 JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putOrderedInt(JNIEnv *env, jobject _this, jobject o, jlong offset, jint x)
 {
-       UNSAFE_PUT_VOLATILE(int32_t);
+       FieldAccess::set_volatile(o, offset, x);
 }
 
 
@@ -1202,7 +1056,7 @@ JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putOrderedInt(JNIEnv *env, jobject _
  */
 JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putOrderedLong(JNIEnv *env, jobject _this, jobject o, jlong offset, jlong x)
 {
-       UNSAFE_PUT_VOLATILE(int64_t);
+       FieldAccess::set_volatile(o, offset, x);
 }
 
 
@@ -1290,10 +1144,12 @@ static JNINativeMethod methods[] = {
        { (char*) "compareAndSwapLong",     (char*) "(Ljava/lang/Object;JJJ)Z",                                   (void*) (uintptr_t) &Java_sun_misc_Unsafe_compareAndSwapLong               },
        { (char*) "getObjectVolatile",      (char*) "(Ljava/lang/Object;J)Ljava/lang/Object;",                    (void*) (uintptr_t) &Java_sun_misc_Unsafe_getObjectVolatile                },
        { (char*) "putObjectVolatile",      (char*) "(Ljava/lang/Object;JLjava/lang/Object;)V",                   (void*) (uintptr_t) &Java_sun_misc_Unsafe_putObjectVolatile                },
+       { (char*) "getByteVolatile",        (char*) "(Ljava/lang/Object;J)B",                                     (void*) (uintptr_t) &Java_sun_misc_Unsafe_getByteVolatile                  },
        { (char*) "getIntVolatile",         (char*) "(Ljava/lang/Object;J)I",                                     (void*) (uintptr_t) &Java_sun_misc_Unsafe_getIntVolatile                   },
        { (char*) "putIntVolatile",         (char*) "(Ljava/lang/Object;JI)V",                                    (void*) (uintptr_t) &Java_sun_misc_Unsafe_putIntVolatile                   },
        { (char*) "getLongVolatile",        (char*) "(Ljava/lang/Object;J)J",                                     (void*) (uintptr_t) &Java_sun_misc_Unsafe_getLongVolatile                  },
        { (char*) "putLongVolatile",        (char*) "(Ljava/lang/Object;JJ)V",                                    (void*) (uintptr_t) &Java_sun_misc_Unsafe_putLongVolatile                  },
+       { (char*) "getFloatVolatile",       (char*) "(Ljava/lang/Object;J)F",                                     (void*) (uintptr_t) &Java_sun_misc_Unsafe_getFloatVolatile                 },
        { (char*) "getDoubleVolatile",      (char*) "(Ljava/lang/Object;J)D",                                     (void*) (uintptr_t) &Java_sun_misc_Unsafe_getDoubleVolatile                },
        { (char*) "putOrderedObject",       (char*) "(Ljava/lang/Object;JLjava/lang/Object;)V",                   (void*) (uintptr_t) &Java_sun_misc_Unsafe_putOrderedObject                 },
        { (char*) "putOrderedInt",          (char*) "(Ljava/lang/Object;JI)V",                                    (void*) (uintptr_t) &Java_sun_misc_Unsafe_putOrderedInt                    },
@@ -1309,18 +1165,15 @@ static JNINativeMethod methods[] = {
 
 *******************************************************************************/
 
-// FIXME
-extern "C" {
 void _Jv_sun_misc_Unsafe_init(void)
 {
-       utf *u;
+       utf* u = utf_new_char("sun/misc/Unsafe");
 
-       u = utf_new_char("sun/misc/Unsafe");
-
-       native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+       NativeMethods& nm = VM::get_current()->get_nativemethods();
+       nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
 }
 
+
 /*
  * These are local overrides for various environment variables in Emacs.
  * Please do not remove this and leave it at the end of the file, where
@@ -1332,4 +1185,5 @@ void _Jv_sun_misc_Unsafe_init(void)
  * c-basic-offset: 4
  * tab-width: 4
  * End:
+ * vim:noexpandtab:sw=4:ts=4:
  */
index 68cdfd9ec4d5c5c5b8373aa33cc3a9fa55949196..b8c40a9ae558ec8e4b018c747b02a27e09eff58e 100644 (file)
@@ -52,11 +52,14 @@ libthreads_la_SOURCES = \
        atomic.cpp \
        atomic.hpp \
        condition.hpp \
-       lock-common.h \
+       lock.cpp \
+       lock.hpp \
+       lockword.cpp \
+       lockword.hpp \
        removeme.cpp \
        mutex.hpp \
-       threadlist.c \
-       threadlist.h \
+       threadlist.cpp \
+       threadlist.hpp \
        thread.cpp \
        thread.hpp
 else
diff --git a/src/threads/lock-common.h b/src/threads/lock-common.h
deleted file mode 100644 (file)
index e0a8f67..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-/* src/threads/lock-common.h - common stuff of lock implementation
-
-   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 _LOCK_COMMON_H
-#define _LOCK_COMMON_H
-
-#include "config.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "vm/types.h"
-
-#include "vm/global.h"
-
-#if defined(ENABLE_THREADS)
-# include "threads/posix/lock.h"
-#else
-# include "threads/none/lock.h"
-#endif
-
-
-/* only define the following stuff with thread enabled ************************/
-
-#if defined(ENABLE_THREADS)
-
-/* functions ******************************************************************/
-
-void lock_init(void);
-
-void lock_init_object_lock(java_object_t *);
-
-ptrint lock_pre_compute_thinlock(s4 index);
-
-bool lock_monitor_enter(java_handle_t *);
-bool lock_monitor_exit(java_handle_t *);
-
-#define LOCK_monitor_enter    (functionptr) lock_monitor_enter
-#define LOCK_monitor_exit     (functionptr) lock_monitor_exit
-
-bool lock_is_held_by_current_thread(java_handle_t *o);
-
-void lock_wait_for_object(java_handle_t *o, s8 millis, s4 nanos);
-void lock_notify_object(java_handle_t *o);
-void lock_notify_all_object(java_handle_t *o);
-
-#endif /* ENABLE_THREADS */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _LOCK_COMMON_H */
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
diff --git a/src/threads/lock.cpp b/src/threads/lock.cpp
new file mode 100644 (file)
index 0000000..5bcee69
--- /dev/null
@@ -0,0 +1,1392 @@
+/* src/threads/lock.cpp - lock implementation
+
+   Copyright (C) 1996-2005, 2006, 2007, 2008
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+   This file is part of CACAO.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+*/
+
+
+#include "config.h"
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/time.h>
+
+#include "vm/types.h"
+
+#include "mm/memory.h"
+
+#include "native/llni.h"
+
+#include "threads/atomic.hpp"
+#include "threads/lock.hpp"
+#include "threads/mutex.hpp"
+#include "threads/threadlist.hpp"
+#include "threads/thread.hpp"
+
+#include "toolbox/list.hpp"
+
+#include "vm/exceptions.hpp"
+#include "vm/finalizer.h"
+#include "vm/global.h"
+#include "vm/options.h"
+#include "vm/string.hpp"
+#include "vm/vm.hpp"
+
+#if defined(ENABLE_STATISTICS)
+# include "vm/statistics.h"
+#endif
+
+#if defined(ENABLE_VMLOG)
+#include <vmlog_cacao.h>
+#endif
+
+#if defined(ENABLE_JVMTI)
+#include "native/jvmti/cacaodbg.h"
+#endif
+
+#if defined(ENABLE_GC_BOEHM)
+# include "mm/boehm-gc/include/gc.h"
+#endif
+
+
+/* debug **********************************************************************/
+
+#if !defined(NDEBUG)
+# define DEBUGLOCKS(format) \
+    do { \
+        if (opt_DebugLocks) { \
+            log_println format; \
+        } \
+    } while (0)
+#else
+# define DEBUGLOCKS(format)
+#endif
+
+
+/******************************************************************************/
+/* MACROS                                                                     */
+/******************************************************************************/
+
+/* number of lock records in the first pool allocated for a thread */
+#define LOCK_INITIAL_LOCK_RECORDS 8
+
+#define LOCK_INITIAL_HASHTABLE_SIZE  1613  /* a prime in the middle between 1024 and 2048 */
+
+
+/******************************************************************************/
+/* MACROS FOR THIN/FAT LOCKS                                                  */
+/******************************************************************************/
+
+/* We use a variant of the tasuki locks described in the paper
+ *     
+ *     Tamiya Onodera, Kiyokuni Kawachiya
+ *     A Study of Locking Objects with Bimodal Fields
+ *     Proceedings of the ACM OOPSLA '99, pp. 223-237
+ *     1999
+ *
+ * The underlying thin locks are a variant of the thin locks described in
+ * 
+ *     Bacon, Konuru, Murthy, Serrano
+ *     Thin Locks: Featherweight Synchronization for Java
+ *        Proceedings of the ACM Conference on Programming Language Design and 
+ *        Implementation (Montreal, Canada), SIGPLAN Notices volume 33, number 6,
+ *        June 1998
+ *
+ * In thin lock mode the lockword looks like this:
+ *
+ *     ,----------------------,-----------,---,
+ *     |      thread ID       |   count   | 0 |
+ *     `----------------------'-----------'---'
+ *
+ *     thread ID......the 'index' of the owning thread, or 0
+ *     count..........number of times the lock has been entered        minus 1
+ *     0..............the shape bit is 0 in thin lock mode
+ *
+ * In fat lock mode it is basically a lock_record_t *:
+ *
+ *     ,----------------------------------,---,
+ *     |    lock_record_t * (without LSB) | 1 |
+ *     `----------------------------------'---'
+ *
+ *     1..............the shape bit is 1 in fat lock mode
+ */
+
+/* global variables ***********************************************************/
+
+/* hashtable mapping objects to lock records */
+static lock_hashtable_t lock_hashtable;
+
+
+/******************************************************************************/
+/* PROTOTYPES                                                                 */
+/******************************************************************************/
+
+static void lock_hashtable_init(void);
+
+static inline Lockword* lock_lockword_get(java_handle_t* o);
+static void lock_record_enter(threadobject *t, lock_record_t *lr);
+static void lock_record_exit(threadobject *t, lock_record_t *lr);
+static bool lock_record_wait(threadobject *t, lock_record_t *lr, s8 millis, s4 nanos);
+static void lock_record_notify(threadobject *t, lock_record_t *lr, bool one);
+
+
+/*============================================================================*/
+/* INITIALIZATION OF DATA STRUCTURES                                          */
+/*============================================================================*/
+
+
+/* lock_init *******************************************************************
+
+   Initialize global data for locking.
+
+*******************************************************************************/
+
+void lock_init(void)
+{
+       /* initialize lock hashtable */
+
+       lock_hashtable_init();
+
+#if defined(ENABLE_VMLOG)
+       vmlog_cacao_init_lock();
+#endif
+}
+
+
+/* lock_record_new *************************************************************
+
+   Allocate a lock record.
+
+*******************************************************************************/
+
+static lock_record_t *lock_record_new(void)
+{
+       lock_record_t *lr;
+
+       /* allocate the data structure on the C heap */
+
+       lr = NEW(lock_record_t);
+
+#if defined(ENABLE_STATISTICS)
+       if (opt_stat)
+               size_lock_record += sizeof(lock_record_t);
+#endif
+
+       /* initialize the members */
+
+       lr->object  = NULL;
+       lr->owner   = NULL;
+       lr->count   = 0;
+       lr->waiters = new List<threadobject*>();
+
+#if defined(ENABLE_GC_CACAO)
+       /* register the lock object as weak reference with the GC */
+
+       gc_weakreference_register(&(lr->object), GC_REFTYPE_LOCKRECORD);
+#endif
+
+       // Initialize the mutex.
+       lr->mutex = new Mutex();
+
+       DEBUGLOCKS(("[lock_record_new   : lr=%p]", (void *) lr));
+
+       return lr;
+}
+
+
+/* lock_record_free ************************************************************
+
+   Free a lock record.
+
+   IN:
+       lr....lock record to free
+
+*******************************************************************************/
+
+static void lock_record_free(lock_record_t *lr)
+{
+       DEBUGLOCKS(("[lock_record_free  : lr=%p]", (void *) lr));
+
+       // Destroy the mutex.
+       delete lr->mutex;
+
+#if defined(ENABLE_GC_CACAO)
+       /* unregister the lock object reference with the GC */
+
+       gc_weakreference_unregister(&(lr->object));
+#endif
+
+       // Free the waiters list.
+       delete lr->waiters;
+
+       /* Free the data structure. */
+
+       FREE(lr, lock_record_t);
+
+#if defined(ENABLE_STATISTICS)
+       if (opt_stat)
+               size_lock_record -= sizeof(lock_record_t);
+#endif
+}
+
+
+/*============================================================================*/
+/* HASHTABLE MAPPING OBJECTS TO LOCK RECORDS                                  */
+/*============================================================================*/
+
+/* lock_hashtable_init *********************************************************
+
+   Initialize the global hashtable mapping objects to lock records.
+
+*******************************************************************************/
+
+static void lock_hashtable_init(void)
+{
+       lock_hashtable.mutex   = new Mutex();
+
+       lock_hashtable.size    = LOCK_INITIAL_HASHTABLE_SIZE;
+       lock_hashtable.entries = 0;
+       lock_hashtable.ptr     = MNEW(lock_record_t *, lock_hashtable.size);
+
+#if defined(ENABLE_STATISTICS)
+       if (opt_stat)
+               size_lock_hashtable += sizeof(lock_record_t *) * lock_hashtable.size;
+#endif
+
+       MZERO(lock_hashtable.ptr, lock_record_t *, lock_hashtable.size);
+}
+
+
+/* lock_hashtable_grow *********************************************************
+
+   Grow the lock record hashtable to about twice its current size and
+   rehash the entries.
+
+*******************************************************************************/
+
+/* must be called with hashtable mutex locked */
+static void lock_hashtable_grow(void)
+{
+       u4 oldsize;
+       u4 newsize;
+       lock_record_t **oldtable;
+       lock_record_t **newtable;
+       lock_record_t *lr;
+       lock_record_t *next;
+       u4 i;
+       u4 h;
+       u4 newslot;
+
+       /* allocate a new table */
+
+       oldsize = lock_hashtable.size;
+       newsize = oldsize*2 + 1; /* XXX should use prime numbers */
+
+       DEBUGLOCKS(("growing lock hashtable to size %d", newsize));
+
+       oldtable = lock_hashtable.ptr;
+       newtable = MNEW(lock_record_t *, newsize);
+
+#if defined(ENABLE_STATISTICS)
+       if (opt_stat)
+               size_lock_hashtable += sizeof(lock_record_t *) * newsize;
+#endif
+
+       MZERO(newtable, lock_record_t *, newsize);
+
+       /* rehash the entries */
+
+       for (i = 0; i < oldsize; i++) {
+               lr = oldtable[i];
+               while (lr) {
+                       next = lr->hashlink;
+
+                       h = heap_hashcode(lr->object);
+                       newslot = h % newsize;
+
+                       lr->hashlink = newtable[newslot];
+                       newtable[newslot] = lr;
+
+                       lr = next;
+               }
+       }
+
+       /* replace the old table */
+
+       lock_hashtable.ptr  = newtable;
+       lock_hashtable.size = newsize;
+
+       MFREE(oldtable, lock_record_t *, oldsize);
+
+#if defined(ENABLE_STATISTICS)
+       if (opt_stat)
+               size_lock_hashtable -= sizeof(lock_record_t *) * oldsize;
+#endif
+}
+
+
+/* lock_hashtable_cleanup ******************************************************
+
+   Removes (and frees) lock records which have a cleared object reference
+   from the hashtable. The locked object was reclaimed by the GC.
+
+*******************************************************************************/
+
+#if defined(ENABLE_GC_CACAO)
+void lock_hashtable_cleanup(void)
+{
+       threadobject  *t;
+       lock_record_t *lr;
+       lock_record_t *prev;
+       lock_record_t *next;
+       int i;
+
+       t = THREADOBJECT;
+
+       /* lock the hashtable */
+
+       Mutex_lock(lock_hashtable.mutex);
+
+       /* search the hashtable for cleared references */
+
+       for (i = 0; i < lock_hashtable.size; i++) {
+               lr = lock_hashtable.ptr[i];
+               prev = NULL;
+
+               while (lr) {
+                       next = lr->hashlink;
+
+                       /* remove lock records with cleared references */
+
+                       if (lr->object == NULL) {
+
+                               /* unlink the lock record from the hashtable */
+
+                               if (prev == NULL)
+                                       lock_hashtable.ptr[i] = next;
+                               else
+                                       prev->hashlink = next;
+
+                               /* free the lock record */
+
+                               lock_record_free(lr);
+
+                       } else {
+                               prev = lr;
+                       }
+
+                       lr = next;
+               }
+       }
+
+       /* unlock the hashtable */
+
+       Mutex_unlock(lock_hashtable.mutex);
+}
+#endif
+
+
+/* lock_hashtable_get **********************************************************
+
+   Find the lock record for the given object.  If it does not exists,
+   yet, create it and enter it in the hashtable.
+
+   IN:
+         o....the object to look up
+
+   RETURN VALUE:
+      the lock record to use for this object
+
+*******************************************************************************/
+
+#if defined(ENABLE_GC_BOEHM)
+static void lock_record_finalizer(void *object, void *p);
+#endif
+
+static lock_record_t *lock_hashtable_get(java_handle_t* o)
+{
+       // This function is inside a critical section.
+       GCCriticalSection cs;
+
+       u4             slot;
+       lock_record_t *lr;
+
+       Lockword* lockword = lock_lockword_get(o);
+
+       if (lockword->is_fat_lock())
+               return lockword->get_fat_lock();
+
+       // Lock the hashtable.
+       lock_hashtable.mutex->lock();
+
+       /* lookup the lock record in the hashtable */
+
+       slot = heap_hashcode(LLNI_DIRECT(o)) % lock_hashtable.size;
+       lr   = lock_hashtable.ptr[slot];
+
+       for (; lr != NULL; lr = lr->hashlink) {
+               if (lr->object == LLNI_DIRECT(o))
+                       break;
+       }
+
+       if (lr == NULL) {
+               /* not found, we must create a new one */
+
+               lr = lock_record_new();
+
+               lr->object = LLNI_DIRECT(o);
+
+#if defined(ENABLE_GC_BOEHM)
+               /* register new finalizer to clean up the lock record */
+
+               GC_REGISTER_FINALIZER(LLNI_DIRECT(o), lock_record_finalizer, 0, 0, 0);
+#endif
+
+               /* enter it in the hashtable */
+
+               lr->hashlink             = lock_hashtable.ptr[slot];
+               lock_hashtable.ptr[slot] = lr;
+               lock_hashtable.entries++;
+
+               /* check whether the hash should grow */
+
+               if (lock_hashtable.entries * 3 > lock_hashtable.size * 4) {
+                       lock_hashtable_grow();
+               }
+       }
+
+       // Unlock the hashtable.
+       lock_hashtable.mutex->unlock();
+
+       /* return the new lock record */
+
+       return lr;
+}
+
+
+/* lock_hashtable_remove *******************************************************
+
+   Remove the lock record for the given object from the hashtable
+   and free it afterwards.
+
+   IN:
+       t....the current thread
+       o....the object to look up
+
+*******************************************************************************/
+
+static void lock_hashtable_remove(threadobject *t, java_handle_t *o)
+{
+       lock_record_t *lr;
+       u4             slot;
+       lock_record_t *tmplr;
+
+       // Lock the hashtable.
+       lock_hashtable.mutex->lock();
+
+       /* get lock record */
+
+       Lockword* lockword = lock_lockword_get(o);
+
+       // Sanity check.
+       assert(lockword->is_fat_lock());
+
+       lr = lockword->get_fat_lock();
+
+       /* remove the lock-record from the hashtable */
+
+       slot  = heap_hashcode(LLNI_DIRECT(o)) % lock_hashtable.size;
+       tmplr = lock_hashtable.ptr[slot];
+
+       if (tmplr == lr) {
+               /* special handling if it's the first in the chain */
+
+               lock_hashtable.ptr[slot] = lr->hashlink;
+       }
+       else {
+               for (; tmplr != NULL; tmplr = tmplr->hashlink) {
+                       if (tmplr->hashlink == lr) {
+                               tmplr->hashlink = lr->hashlink;
+                               break;
+                       }
+               }
+
+               assert(tmplr != NULL);
+       }
+
+       /* decrease entry count */
+
+       lock_hashtable.entries--;
+
+       // Unlock the hashtable.
+       lock_hashtable.mutex->unlock();
+
+       /* free the lock record */
+
+       lock_record_free(lr);
+}
+
+
+/* lock_record_finalizer *******************************************************
+
+   XXX Remove me for exact GC.
+
+*******************************************************************************/
+
+static void lock_record_finalizer(void *object, void *p)
+{
+       java_handle_t *o;
+       classinfo     *c;
+
+       o = (java_handle_t *) object;
+
+#if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
+       /* XXX this is only a dirty hack to make Boehm work with handles */
+
+       o = LLNI_WRAP((java_object_t *) o);
+#endif
+
+       LLNI_class_get(o, c);
+
+#if !defined(NDEBUG)
+       if (opt_DebugFinalizer) {
+               log_start();
+               log_print("[finalizer lockrecord: o=%p p=%p class=", object, p);
+               class_print(c);
+               log_print("]");
+               log_finish();
+       }
+#endif
+
+       /* check for a finalizer function */
+
+       if (c->finalizer != NULL)
+               finalizer_run(object, p);
+
+       /* remove the lock-record entry from the hashtable and free it */
+
+       lock_hashtable_remove(THREADOBJECT, o);
+}
+
+
+/*============================================================================*/
+/* LOCKING ALGORITHM                                                          */
+/*============================================================================*/
+
+
+/* lock_lockword_get ***********************************************************
+
+   Get the lockword for the given object.
+
+   IN:
+      o............the object
+
+*******************************************************************************/
+
+static inline Lockword* lock_lockword_get(java_handle_t* o)
+{
+#if defined(ENABLE_GC_CACAO)
+       // Sanity check.
+       assert(GCCriticalSection::inside() == true);
+#endif
+
+       return &(LLNI_DIRECT(o)->lockword);
+}
+
+
+/* lock_record_enter ***********************************************************
+
+   Enter the lock represented by the given lock record.
+
+   IN:
+      t.................the current thread
+         lr................the lock record
+
+*******************************************************************************/
+
+static inline void lock_record_enter(threadobject *t, lock_record_t *lr)
+{
+       lr->mutex->lock();
+       lr->owner = t;
+}
+
+
+/* lock_record_exit ************************************************************
+
+   Release the lock represented by the given lock record.
+
+   IN:
+      t.................the current thread
+         lr................the lock record
+
+   PRE-CONDITION:
+      The current thread must own the lock represented by this lock record.
+         This is NOT checked by this function!
+
+*******************************************************************************/
+
+static inline void lock_record_exit(threadobject *t, lock_record_t *lr)
+{
+       lr->owner = NULL;
+       lr->mutex->unlock();
+}
+
+
+/* lock_inflate ****************************************************************
+
+   Inflate the lock of the given object. This may only be called by the
+   owner of the monitor of the object.
+
+   IN:
+         o............the object of which to inflate the lock
+         lr...........the lock record to install. The current thread must
+                      own the lock of this lock record!
+
+   PRE-CONDITION:
+      The current thread must be the owner of this object's monitor AND
+         of the lock record's lock!
+
+*******************************************************************************/
+
+static void lock_inflate(java_handle_t *o, lock_record_t *lr)
+{
+       Lockword* lockword = lock_lockword_get(o);
+       lockword->inflate(lr);
+}
+
+
+static void sable_flc_waiting(Lockword *lockword, threadobject *t, java_handle_t *o)
+{
+       int32_t index;
+       threadobject *t_other;
+       int old_flc;
+
+       index = lockword->get_thin_lock_thread_index();
+       t_other = ThreadList::get_thread_by_index(index);
+
+       // The lockword could have changed during our way here.  If the
+       // thread index is zero, the lock got unlocked and we simply
+       // return.
+       if (t_other == NULL)
+/*             failure, TODO: add statistics */
+               return;
+
+       t_other->flc_lock->lock();
+       old_flc = t_other->flc_bit;
+       t_other->flc_bit = true;
+
+       DEBUGLOCKS(("thread %d set flc bit for lock-holding thread %d", t->index, t_other->index));
+
+       // Set FLC bit first, then read the lockword again.
+       Atomic::memory_barrier();
+
+       lockword = lock_lockword_get(o);
+
+       /* Lockword is still the way it was seen before */
+       if (lockword->is_thin_lock() && (lockword->get_thin_lock_thread_index() == index))
+       {
+               threadobject *f;
+               /* Add tuple (t, o) to the other thread's FLC list */
+               t->flc_object = o;
+               t->flc_next = t_other->flc_list;
+               t_other->flc_list = t;
+               if (t->flc_next == 0)
+                       t_other->flc_tail = t;
+               f = t_other->flc_tail;
+
+               for (;;)
+               {
+                       threadobject *current;
+
+                       // Wait until another thread sees the flc bit and notifies
+                       // us of unlocking.
+                       t->flc_cond->wait(t_other->flc_lock);
+
+                       if (t_other->flc_tail != f)
+                               break;
+                       /* Traverse FLC list looking if we're still there */
+                       current = t_other->flc_list;
+                       while (current && current != t)
+                               current = current->flc_next;
+                       if (!current)
+                               /* not in list anymore, can stop waiting */
+                               break;
+
+                       /* We are still in the list -- the other thread cannot have seen
+                          the FLC bit yet */
+                       assert(t_other->flc_bit);
+               }
+
+               t->flc_object = NULL;   /* for garbage collector? */
+               t->flc_next = NULL;
+       }
+       else
+               t_other->flc_bit = old_flc;
+
+       t_other->flc_lock->unlock();
+}
+
+static void notify_flc_waiters(threadobject *t, java_handle_t *o)
+{
+       threadobject *current;
+
+       t->flc_lock->lock();
+
+       current = t->flc_list;
+       while (current)
+       {
+               if (current->flc_object != o)
+               {
+                       /* The object has to be inflated so the other threads can properly
+                          block on it. */
+
+                       // Only if not already inflated.
+                       Lockword* lockword = lock_lockword_get(current->flc_object);
+                       if (lockword->is_thin_lock()) {
+                               lock_record_t *lr = lock_hashtable_get(current->flc_object);
+                               lock_record_enter(t, lr);
+
+                               DEBUGLOCKS(("thread %d inflating lock of %p to lr %p",
+                                                       t->index, (void*) current->flc_object, (void*) lr));
+
+                               lock_inflate(current->flc_object, lr);
+                       }
+               }
+
+               // Wake the waiting threads.
+               current->flc_cond->broadcast();
+
+               current = current->flc_next;
+       }
+
+       t->flc_list = NULL;
+       t->flc_bit = false;
+
+       t->flc_lock->unlock();
+}
+
+/* lock_monitor_enter **********************************************************
+
+   Acquire the monitor of the given object. If the current thread already
+   owns the monitor, the lock counter is simply increased.
+
+   This function blocks until it can acquire the monitor.
+
+   IN:
+      t............the current thread
+         o............the object of which to enter the monitor
+
+   RETURN VALUE:
+      true.........the lock has been successfully acquired
+         false........an exception has been thrown
+
+*******************************************************************************/
+
+bool lock_monitor_enter(java_handle_t *o)
+{
+       // This function is inside a critical section.
+       GCCriticalSection cs;
+
+       if (o == NULL) {
+               exceptions_throw_nullpointerexception();
+               return false;
+       }
+
+       threadobject* t = thread_get_current();
+
+       uintptr_t thinlock = t->thinlock;
+
+retry:
+       // Most common case: try to thin-lock an unlocked object.
+       Lockword* lockword = lock_lockword_get(o);
+       bool result = lockword->lock(thinlock);
+
+       if (result == true) {
+               // Success, we locked it.
+               // NOTE: The Java Memory Model requires an instruction barrier
+               // here (because of the CAS above).
+               Atomic::instruction_barrier();
+               return true;
+       }
+
+       // Next common case: recursive lock with small recursion count.
+       // NOTE: We don't have to worry about stale values here, as any
+       // stale value will indicate another thread holding the lock (or
+       // an inflated lock).
+       if (lockword->get_thin_lock_without_count() == thinlock) {
+               // We own this monitor.  Check the current recursion count.
+               if (lockword->is_max_thin_lock_count() == false) {
+                       // The recursion count is low enough.
+                       lockword->increase_thin_lock_count();
+
+                       // Success, we locked it.
+                       return true;
+               }
+               else {
+                       // Recursion count overflow.
+                       lock_record_t* lr = lock_hashtable_get(o);
+                       lock_record_enter(t, lr);
+                       lock_inflate(o, lr);
+                       lr->count++;
+
+                       notify_flc_waiters(t, o);
+
+                       return true;
+               }
+       }
+
+       // The lock is either contented or fat.
+       if (lockword->is_fat_lock()) {
+               lock_record_t* lr = lockword->get_fat_lock();
+
+               // Check for recursive entering.
+               if (lr->owner == t) {
+                       lr->count++;
+                       return true;
+               }
+
+               // Acquire the mutex of the lock record.
+               lock_record_enter(t, lr);
+
+               // Sanity check.
+               assert(lr->count == 0);
+               return true;
+       }
+
+       /****** inflation path ******/
+
+#if defined(ENABLE_JVMTI)
+       /* Monitor Contended Enter */
+       jvmti_MonitorContendedEntering(false, o);
+#endif
+
+       sable_flc_waiting(lockword, t, o);
+
+#if defined(ENABLE_JVMTI)
+       /* Monitor Contended Entered */
+       jvmti_MonitorContendedEntering(true, o);
+#endif
+       goto retry;
+}
+
+
+/* lock_monitor_exit ***********************************************************
+
+   Decrement the counter of a (currently owned) monitor. If the counter
+   reaches zero, release the monitor.
+
+   If the current thread is not the owner of the monitor, an 
+   IllegalMonitorState exception is thrown.
+
+   IN:
+      t............the current thread
+         o............the object of which to exit the monitor
+
+   RETURN VALUE:
+      true.........everything ok,
+         false........an exception has been thrown
+
+*******************************************************************************/
+
+bool lock_monitor_exit(java_handle_t* o)
+{
+       // This function is inside a critical section.
+       GCCriticalSection cs;
+
+       if (o == NULL) {
+               exceptions_throw_nullpointerexception();
+               return false;
+       }
+
+       threadobject* t = thread_get_current();
+
+       uintptr_t thinlock = t->thinlock;
+
+       // We don't have to worry about stale values here, as any stale
+       // value will indicate that we don't own the lock.
+       Lockword* lockword = lock_lockword_get(o);
+
+       // Most common case: we release a thin lock that we hold once.
+       if (lockword->get_thin_lock() == thinlock) {
+               // Memory barrier for Java Memory Model.
+               Atomic::write_memory_barrier();
+               lockword->unlock();
+               // Memory barrier for thin locking.
+               Atomic::memory_barrier();
+
+               /* check if there has been a flat lock contention on this object */
+
+               if (t->flc_bit) {
+                       DEBUGLOCKS(("thread %d saw flc bit", t->index));
+
+                       /* there has been a contention on this thin lock */
+                       notify_flc_waiters(t, o);
+               }
+
+               return true;
+       }
+
+       // Next common case: we release a recursive lock, count > 0.
+       if (lockword->get_thin_lock_without_count() == thinlock) {
+               lockword->decrease_thin_lock_count();
+               return true;
+       }
+
+       // Either the lock is fat, or we don't hold it at all.
+       if (lockword->is_fat_lock()) {
+               lock_record_t* lr = lockword->get_fat_lock();
+
+               // Check if we own this monitor.
+               // NOTE: We don't have to worry about stale values here, as
+               // any stale value will be != t and thus fail this check.
+               if (lr->owner != t) {
+                       exceptions_throw_illegalmonitorstateexception();
+                       return false;
+               }
+
+               /* { the current thread `t` owns the lock record `lr` on object `o` } */
+
+               if (lr->count != 0) {
+                       // We had locked this one recursively.  Just decrement, it
+                       // will still be locked.
+                       lr->count--;
+                       return true;
+               }
+
+               // Unlock this lock record.
+               lock_record_exit(t, lr);
+               return true;
+       }
+
+       // Legal thin lock cases have been handled above, so this is an
+       // error.
+       exceptions_throw_illegalmonitorstateexception();
+
+       return false;
+}
+
+
+/* lock_record_add_waiter ******************************************************
+
+   Add a thread to the list of waiting threads of a lock record.
+
+   IN:
+      lr...........the lock record
+      thread.......the thread to add
+
+*******************************************************************************/
+
+static void lock_record_add_waiter(lock_record_t *lr, threadobject* t)
+{
+       // Add the thread as last entry to waiters list.
+       lr->waiters->push_back(t);
+
+#if defined(ENABLE_STATISTICS)
+       if (opt_stat)
+               size_lock_waiter += sizeof(threadobject*);
+#endif
+}
+
+
+/* lock_record_remove_waiter ***************************************************
+
+   Remove a thread from the list of waiting threads of a lock record.
+
+   IN:
+      lr...........the lock record
+      t............the current thread
+
+   PRE-CONDITION:
+      The current thread must be the owner of the lock record.
+   
+*******************************************************************************/
+
+static void lock_record_remove_waiter(lock_record_t *lr, threadobject* t)
+{
+       // Remove the thread from the waiters.
+       lr->waiters->remove(t);
+
+#if defined(ENABLE_STATISTICS)
+       if (opt_stat)
+               size_lock_waiter -= sizeof(threadobject*);
+#endif
+}
+
+
+/* lock_record_wait ************************************************************
+
+   Wait on a lock record for a given (maximum) amount of time.
+
+   IN:
+      t............the current thread
+         lr...........the lock record
+         millis.......milliseconds of timeout
+         nanos........nanoseconds of timeout
+
+   RETURN VALUE:
+      true.........we have been interrupted,
+      false........everything ok
+
+   PRE-CONDITION:
+      The current thread must be the owner of the lock record.
+         This is NOT checked by this function!
+   
+*******************************************************************************/
+
+static bool lock_record_wait(threadobject *thread, lock_record_t *lr, s8 millis, s4 nanos)
+{
+       s4   lockcount;
+       bool wasinterrupted = false;
+
+       DEBUGLOCKS(("[lock_record_wait  : lr=%p, t=%p, millis=%lld, nanos=%d]",
+                               lr, thread, millis, nanos));
+
+       /* { the thread t owns the fat lock record lr on the object o } */
+
+       /* register us as waiter for this object */
+
+       lock_record_add_waiter(lr, thread);
+
+       /* remember the old lock count */
+
+       lockcount = lr->count;
+
+       /* unlock this record */
+
+       lr->count = 0;
+       lock_record_exit(thread, lr);
+
+       /* wait until notified/interrupted/timed out */
+
+       threads_wait_with_timeout_relative(thread, millis, nanos);
+
+       /* re-enter the monitor */
+
+       lock_record_enter(thread, lr);
+
+       /* remove us from the list of waiting threads */
+
+       lock_record_remove_waiter(lr, thread);
+
+       /* restore the old lock count */
+
+       lr->count = lockcount;
+
+       /* We can only be signaled OR interrupted, not both. If both flags
+          are set, reset only signaled and leave the thread in
+          interrupted state. Otherwise, clear both. */
+
+       if (!thread->signaled) {
+               wasinterrupted = thread->interrupted;
+               thread->interrupted = false;
+       }
+
+       thread->signaled = false;
+
+       /* return if we have been interrupted */
+
+       return wasinterrupted;
+}
+
+
+/* lock_monitor_wait ***********************************************************
+
+   Wait on an object for a given (maximum) amount of time.
+
+   IN:
+      t............the current thread
+         o............the object
+         millis.......milliseconds of timeout
+         nanos........nanoseconds of timeout
+
+   PRE-CONDITION:
+      The current thread must be the owner of the object's monitor.
+   
+*******************************************************************************/
+
+static void lock_monitor_wait(threadobject *t, java_handle_t *o, s8 millis, s4 nanos)
+{
+       lock_record_t *lr;
+
+       Lockword* lockword = lock_lockword_get(o);
+
+       // Check if we own this monitor.
+       // NOTE: We don't have to worry about stale values here, as any
+       // stale value will fail this check.
+       if (lockword->is_fat_lock()) {
+               lr = lockword->get_fat_lock();
+
+               if (lr->owner != t) {
+                       exceptions_throw_illegalmonitorstateexception();
+                       return;
+               }
+       }
+       else {
+               // It's a thin lock.
+               if (lockword->get_thin_lock_without_count() != t->thinlock) {
+                       exceptions_throw_illegalmonitorstateexception();
+                       return;
+               }
+
+               // Get the lock-record.
+               lr = lock_hashtable_get(o);
+               lock_record_enter(t, lr);
+
+               // Inflate this lock.
+               lockword->inflate(lr);
+
+               notify_flc_waiters(t, o);
+       }
+
+       /* { the thread t owns the fat lock record lr on the object o } */
+
+       if (lock_record_wait(t, lr, millis, nanos))
+               exceptions_throw_interruptedexception();
+}
+
+
+/* lock_record_notify **********************************************************
+
+   Notify one thread or all threads waiting on the given lock record.
+
+   IN:
+      t............the current thread
+         lr...........the lock record
+         one..........if true, only notify one thread
+
+   PRE-CONDITION:
+      The current thread must be the owner of the lock record.
+         This is NOT checked by this function!
+   
+*******************************************************************************/
+
+static void lock_record_notify(threadobject *t, lock_record_t *lr, bool one)
+{
+#if defined(ENABLE_GC_CACAO)
+       // Sanity check.
+       assert(GCCriticalSection::inside() == false);
+#endif
+
+       // { The thread t owns the fat lock record lr on the object o }
+
+       for (List<threadobject*>::iterator it = lr->waiters->begin(); it != lr->waiters->end(); it++) {
+               threadobject* waiter = *it;
+
+               // We must skip threads which have already been notified. They
+               // will remove themselves from the list.
+               if (waiter->signaled)
+                       continue;
+
+               // Enter the wait-mutex.
+               waiter->waitmutex->lock();
+
+               DEBUGLOCKS(("[lock_record_notify: lr=%p, t=%p, waitingthread=%p, one=%d]", lr, t, waiter, one));
+
+               // Signal the waiter.
+               waiter->waitcond->signal();
+
+               // Mark the thread as signaled.
+               waiter->signaled = true;
+
+               // Leave the wait-mutex.
+               waiter->waitmutex->unlock();
+
+               // If we should only wake one thread, we are done.
+               if (one)
+                       break;
+       }
+}
+
+
+/* lock_monitor_notify *********************************************************
+
+   Notify one thread or all threads waiting on the given object.
+
+   IN:
+      t............the current thread
+         o............the object
+         one..........if true, only notify one thread
+
+   PRE-CONDITION:
+      The current thread must be the owner of the object's monitor.
+   
+*******************************************************************************/
+
+static void lock_monitor_notify(threadobject *t, java_handle_t *o, bool one)
+{
+       lock_record_t* lr = NULL;
+
+       {
+               // This scope is inside a critical section.
+               GCCriticalSection cs;
+
+               Lockword* lockword = lock_lockword_get(o);
+
+               // Check if we own this monitor.
+               // NOTE: We don't have to worry about stale values here, as any
+               // stale value will fail this check.
+
+               if (lockword->is_fat_lock()) {
+                       lr = lockword->get_fat_lock();
+
+                       if (lr->owner != t) {
+                               exceptions_throw_illegalmonitorstateexception();
+                               return;
+                       }
+               }
+               else {
+                       // It's a thin lock.
+                       if (lockword->get_thin_lock_without_count() != t->thinlock) {
+                               exceptions_throw_illegalmonitorstateexception();
+                               return;
+                       }
+
+                       // No thread can wait on a thin lock, so there's nothing to do.
+                       return;
+               }
+       }
+
+       // { The thread t owns the fat lock record lr on the object o }
+       lock_record_notify(t, lr, one);
+}
+
+
+
+/*============================================================================*/
+/* INQUIRY FUNCIONS                                                           */
+/*============================================================================*/
+
+
+/* lock_is_held_by_current_thread **********************************************
+
+   Return true if the current thread owns the monitor of the given object.
+
+   IN:
+         o............the object
+
+   RETURN VALUE:
+      true, if the current thread holds the lock of this object.
+   
+*******************************************************************************/
+
+bool lock_is_held_by_current_thread(java_handle_t *o)
+{
+       // This function is inside a critical section.
+       GCCriticalSection cs;
+
+       // Check if we own this monitor.
+       // NOTE: We don't have to worry about stale values here, as any
+       // stale value will fail this check.
+       threadobject* t = thread_get_current();
+       Lockword* lockword = lock_lockword_get(o);
+
+       if (lockword->is_fat_lock()) {
+               // It's a fat lock.
+               lock_record_t* lr = lockword->get_fat_lock();
+               return (lr->owner == t);
+       }
+       else {
+               // It's a thin lock.
+               return (lockword->get_thin_lock_without_count() == t->thinlock);
+       }
+}
+
+
+
+/*============================================================================*/
+/* WRAPPERS FOR OPERATIONS ON THE CURRENT THREAD                              */
+/*============================================================================*/
+
+
+/* lock_wait_for_object ********************************************************
+
+   Wait for the given object.
+
+   IN:
+         o............the object
+         millis.......milliseconds to wait
+         nanos........nanoseconds to wait
+   
+*******************************************************************************/
+
+void lock_wait_for_object(java_handle_t *o, s8 millis, s4 nanos)
+{
+       threadobject *thread;
+
+       thread = THREADOBJECT;
+
+       lock_monitor_wait(thread, o, millis, nanos);
+}
+
+
+/* lock_notify_object **********************************************************
+
+   Notify one thread waiting on the given object.
+
+   IN:
+         o............the object
+   
+*******************************************************************************/
+
+void lock_notify_object(java_handle_t *o)
+{
+       threadobject *thread;
+
+       thread = THREADOBJECT;
+
+       lock_monitor_notify(thread, o, true);
+}
+
+
+/* lock_notify_all_object ******************************************************
+
+   Notify all threads waiting on the given object.
+
+   IN:
+         o............the object
+   
+*******************************************************************************/
+
+void lock_notify_all_object(java_handle_t *o)
+{
+       threadobject *thread;
+
+       thread = THREADOBJECT;
+
+       lock_monitor_notify(thread, o, false);
+}
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
diff --git a/src/threads/lock.hpp b/src/threads/lock.hpp
new file mode 100644 (file)
index 0000000..87519d9
--- /dev/null
@@ -0,0 +1,131 @@
+/* src/threads/lock.hpp - lock implementation
+
+   Copyright (C) 1996-2005, 2006, 2007, 2008
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+   This file is part of CACAO.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+*/
+
+
+#ifndef _LOCK_HPP
+#define _LOCK_HPP
+
+#include <stdint.h>
+
+#include "native/llni.h"
+
+#include "threads/mutex.hpp"
+
+#include "toolbox/list.hpp"
+
+#include "vm/global.h"
+
+
+/* typedefs *******************************************************************/
+
+typedef struct lock_record_t    lock_record_t;
+typedef struct lock_hashtable_t lock_hashtable_t;
+
+
+/* lock_record_t ***************************************************************
+
+   Lock record struct representing an inflated ("fat") lock.
+
+*******************************************************************************/
+
+struct lock_record_t {
+       java_object_t       *object;             /* object for which this lock is */
+       struct threadobject *owner;              /* current owner of this monitor */
+       s4                   count;              /* recursive lock count          */
+       Mutex*               mutex;              /* mutex for synchronizing       */
+#ifdef __cplusplus
+       List<threadobject*>* waiters;            /* list of threads waiting       */
+#else
+       List* waiters;
+#endif
+       lock_record_t       *hashlink;           /* next record in hash chain     */
+};
+
+
+/* lock_hashtable_t ************************************************************
+   The global hashtable mapping objects to lock records.
+
+*******************************************************************************/
+
+struct lock_hashtable_t {
+    Mutex*               mutex;       /* mutex for synch. access to the table */
+       u4                   size;        /* number of slots                      */
+       u4                   entries;     /* current number of entries            */
+       lock_record_t      **ptr;         /* the table of slots, uses ext. chain. */
+};
+
+
+/* functions ******************************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void lock_init(void);
+
+bool lock_monitor_enter(java_handle_t *);
+bool lock_monitor_exit(java_handle_t *);
+
+#define LOCK_monitor_enter    (functionptr) lock_monitor_enter
+#define LOCK_monitor_exit     (functionptr) lock_monitor_exit
+
+bool lock_is_held_by_current_thread(java_handle_t *o);
+
+void lock_wait_for_object(java_handle_t *o, s8 millis, s4 nanos);
+void lock_notify_object(java_handle_t *o);
+void lock_notify_all_object(java_handle_t *o);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+/* defines ********************************************************************/
+
+/* only define the following stuff with thread enabled ************************/
+
+#if defined(ENABLE_THREADS)
+
+#define LOCK_MONITOR_ENTER(o)    lock_monitor_enter((java_handle_t *) LLNI_QUICKWRAP(o))
+#define LOCK_MONITOR_EXIT(o)     lock_monitor_exit((java_handle_t *) LLNI_QUICKWRAP(o))
+
+#endif
+
+#endif // _LOCK_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:
+ */
diff --git a/src/threads/lockword.cpp b/src/threads/lockword.cpp
new file mode 100644 (file)
index 0000000..78dc849
--- /dev/null
@@ -0,0 +1,82 @@
+/* src/threads/lockword.cpp - lockword implementation
+
+   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 <assert.h>
+#include <stdint.h>
+
+#include "threads/lock.hpp"
+
+
+/**
+ * Inflate the lock of the given object. This may only be called by
+ * the owner of the monitor of the object.
+ * 
+ * PRE-CONDITION: The current thread must be the owner of this
+ * object's monitor AND of the lock record's lock!
+ *
+ * @param lr The lock-record to install.  The current thread must own
+ *              the lock of this lock record!
+ */
+void Lockword::inflate(lock_record_t* lr)
+{
+       if (is_fat_lock()) {
+               // Sanity check.
+               assert(get_fat_lock() == lr);
+               return;
+       }
+
+       // Sanity check.
+       assert(get_thin_lock_without_count() == thread_get_current()->thinlock);
+
+       // Copy the count from the thinlock.
+       lr->count = get_thin_lock_count();
+
+//     DEBUGLOCKS(("[lock_inflate      : lr=%p, t=%p, o=%p, o->lockword=%lx, count=%d]",
+//                             lr, thread_get_current(), o, get_thin_lock(), lr->count));
+
+       // Install the lock-record in the lockword.
+       set(lr);
+}
+
+
+extern "C" {
+       void Lockword_init(Lockword* lockword) { lockword->init(); }
+}
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
diff --git a/src/threads/lockword.hpp b/src/threads/lockword.hpp
new file mode 100644 (file)
index 0000000..b940d60
--- /dev/null
@@ -0,0 +1,250 @@
+/* src/threads/lockword.hpp - lockword implementation
+
+   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 _LOCKWORD_HPP
+#define _LOCKWORD_HPP
+
+#include <stdint.h>
+
+
+#ifdef __cplusplus
+
+/**
+ * Lockword.
+ */
+class Lockword {
+private:
+       static const int       THIN_LOCK_WORD_SIZE   = SIZEOF_VOID_P * 8; // Pointer size multiplied by 8-bit.
+       static const int       THIN_LOCK_SHAPE_BIT   = 0x01;
+
+       static const uintptr_t THIN_UNLOCKED         = 0;
+
+       static const int       THIN_LOCK_COUNT_SHIFT = 1;
+       static const int       THIN_LOCK_COUNT_SIZE  = 8;
+       static const int       THIN_LOCK_COUNT_INCR  = (1 << THIN_LOCK_COUNT_SHIFT);
+       static const int       THIN_LOCK_COUNT_MAX   = ((1 << THIN_LOCK_COUNT_SIZE) - 1);
+
+       static const int       THIN_LOCK_COUNT_MASK  = (THIN_LOCK_COUNT_MAX << THIN_LOCK_COUNT_SHIFT);
+
+       static const int       THIN_LOCK_TID_SHIFT   = (THIN_LOCK_COUNT_SIZE + THIN_LOCK_COUNT_SHIFT);
+       static const int       THIN_LOCK_TID_SIZE    = (THIN_LOCK_WORD_SIZE - THIN_LOCK_TID_SHIFT);
+
+private:
+       // The actual lockword.
+       uintptr_t _lockword;
+
+private:
+       Lockword(uintptr_t lockword) : _lockword(lockword) {}
+
+public:
+       Lockword() : _lockword(THIN_UNLOCKED) {}
+
+       void init() { _lockword = THIN_UNLOCKED; } // REMOVEME
+
+       static inline uintptr_t pre_compute_thinlock(int32_t index);
+
+       inline bool is_thin_lock         () const;
+       inline bool is_fat_lock          () const;
+
+       inline bool is_unlocked() const;
+       inline bool lock       (uintptr_t thinlock);
+       inline void unlock     ();
+
+       inline uintptr_t             get_thin_lock              () const;
+       inline uintptr_t             get_thin_lock_without_count() const;
+       inline int32_t               get_thin_lock_count        () const;
+       inline int32_t               get_thin_lock_thread_index () const;
+       inline struct lock_record_t* get_fat_lock               () const;
+
+       inline void set(uintptr_t lockword);
+       inline void set(struct lock_record_t* lr);
+
+       inline bool is_max_thin_lock_count  () const;
+       inline void increase_thin_lock_count();
+       inline void decrease_thin_lock_count();
+
+       void inflate(struct lock_record_t* lr);
+};
+
+
+// Includes.
+#include <assert.h>
+
+#include "threads/atomic.hpp"
+
+
+/**
+ * Pre-compute the thin lock value for a thread index.
+ *
+ * @param index The thead index (>= 1).
+ *
+ * @return The thin lock value for this thread index.
+ */
+uintptr_t Lockword::pre_compute_thinlock(int32_t index)
+{
+       return (index << THIN_LOCK_TID_SHIFT) | THIN_UNLOCKED;
+}
+
+
+bool Lockword::is_thin_lock() const
+{
+       return ((_lockword & THIN_LOCK_SHAPE_BIT) == 0);
+}
+
+
+bool Lockword::is_fat_lock() const
+{
+       return ((_lockword & THIN_LOCK_SHAPE_BIT) != 0);
+}
+
+
+/**
+ * Check if the lockword is an unlocked thin-lock.
+ *
+ * @return true if unlocked, false otherwise.
+ */
+bool Lockword::is_unlocked() const
+{
+       return (_lockword == THIN_UNLOCKED);
+}
+
+
+/**
+ * Try to lock the lockword with the given thin-lock value.
+ *
+ * @param thinlock Thin-lock value to store in the Lockword.
+ *
+ * @return true if lock was successful, false otherwise.
+ */
+bool Lockword::lock(uintptr_t thinlock)
+{
+       // Atomically exchange the lockword value.
+       uintptr_t oldlockword = Atomic::compare_and_swap(&_lockword, THIN_UNLOCKED, thinlock);
+
+       return Lockword(oldlockword).is_unlocked();
+}
+
+
+/**
+ * Set the lockword to THIN_UNLOCKED.
+ */
+void Lockword::unlock()
+{
+       _lockword = THIN_UNLOCKED;
+}
+
+
+uintptr_t Lockword::get_thin_lock() const
+{
+       return _lockword;
+}
+
+
+uintptr_t Lockword::get_thin_lock_without_count() const
+{
+       return (_lockword & ~THIN_LOCK_COUNT_MASK);
+}
+
+
+int32_t Lockword::get_thin_lock_count() const
+{
+       return (int32_t) (_lockword & THIN_LOCK_COUNT_MASK) >> THIN_LOCK_COUNT_SHIFT;
+}
+
+
+int32_t Lockword::get_thin_lock_thread_index() const
+{
+       return (int32_t) (_lockword >> THIN_LOCK_TID_SHIFT);
+}
+
+
+struct lock_record_t* Lockword::get_fat_lock() const
+{
+       return (struct lock_record_t*) (_lockword & ~THIN_LOCK_SHAPE_BIT);
+}
+
+
+void Lockword::set(uintptr_t lockword)
+{
+       _lockword = lockword;
+}
+
+
+void Lockword::set(struct lock_record_t* lr)
+{
+       _lockword = ((uintptr_t) lr) | THIN_LOCK_SHAPE_BIT;
+}
+
+
+bool Lockword::is_max_thin_lock_count() const
+{
+       return (get_thin_lock_count() >= THIN_LOCK_COUNT_MAX);
+}
+
+
+void Lockword::increase_thin_lock_count()
+{
+       // Sanity check.
+       assert(get_thin_lock_count() < THIN_LOCK_COUNT_MAX);
+
+       _lockword += (1 << THIN_LOCK_COUNT_SHIFT);
+}
+
+
+void Lockword::decrease_thin_lock_count()
+{
+       // Sanity check.
+       assert(get_thin_lock_count() > 0);
+
+       _lockword -= (1 << THIN_LOCK_COUNT_SHIFT);
+}
+
+#else
+
+// This structure must have the same layout as the C++ class above.
+typedef struct Lockword {
+       uintptr_t _lockword;
+} Lockword;
+
+void Lockword_init(Lockword* lockword);
+
+#endif
+
+#endif // _LOCKWORD_HPP
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
index dcf09918d5eb036dcdd2d2fed7560e647ee37b91..5a48ae5327fdce600d8d755d6265cdca3d2173f9 100644 (file)
@@ -30,8 +30,6 @@
 
 /* define some stuff to no-ops *************************************************/
 
-#define LOCK_INIT_OBJECT_LOCK(o)
-
 #define LOCK_MONITOR_ENTER(o)
 #define LOCK_MONITOR_EXIT(o)
 
index bd149bc3773937a1c1f757ec837281df71a72e44..21b3bee53b8cf73403718484afa884855ea1f336 100644 (file)
@@ -32,7 +32,8 @@
 
 #include "vm/types.h"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
+#include "vm/globals.hpp"
 
 #include "vm/jit/stacktrace.hpp"
 
index c4a9f73613f84842d724fc677988ae6d575a63da..4abed884a9f27f3b05c49d9b4187aca0d52a70ff 100644 (file)
@@ -30,8 +30,6 @@ noinst_LTLIBRARIES = \
 
 libthreadsposix_la_SOURCES = \
        condition-posix.hpp \
-       lock.c \
-       lock.h \
        mutex-posix.hpp \
        thread-posix.cpp \
        thread-posix.hpp
index 4c8afc060baf4dcef9d333abf0f85a38cafdf241..6df1cda87dbdcf3195ed04c9368a248cf3cd7876 100644 (file)
@@ -31,7 +31,6 @@
 #include <pthread.h>
 #include <time.h>
 
-#include "vm/vm.hpp"
 
 #ifdef __cplusplus
 
@@ -51,20 +50,28 @@ public:
        void signal();
        void timedwait(Mutex* mutex, const struct timespec* abstime);
        void wait(Mutex* mutex);
+       void wait(Mutex& mutex);
 };
 
 
+// Includes.
+#include "vm/vm.hpp"
+
+
+// Includes.
+#include "vm/os.hpp"
+
+
 /**
  * Initialize a POSIX condition variable.
  */
 inline Condition::Condition()
 {
-       int result;
+       int result = pthread_cond_init(&_cond, NULL);
 
-       result = pthread_cond_init(&_cond, NULL);
-
-       if (result != 0)
-               vm_abort_errnum(result, "Condition::Condition(): pthread_cond_init failed");
+       if (result != 0) {
+               os::abort_errnum(result, "Condition::Condition(): pthread_cond_init failed");
+       }
 }
 
 
@@ -73,12 +80,14 @@ inline Condition::Condition()
  */
 inline Condition::~Condition()
 {
-       int result;
+       // Restart all threads waiting on this condition.
+       broadcast();
 
-       result = pthread_cond_destroy(&_cond);
+       int result = pthread_cond_destroy(&_cond);
 
-       if (result != 0)
-               vm_abort_errnum(result, "Condition::~Condition(): pthread_cond_destroy failed");
+       if (result != 0) {
+               os::abort_errnum(result, "Condition::~Condition(): pthread_cond_destroy failed");
+       }
 }
 
 
@@ -88,12 +97,11 @@ inline Condition::~Condition()
  */
 inline void Condition::broadcast()
 {
-       int result;
-
-       result = pthread_cond_broadcast(&_cond);
+       int result = pthread_cond_broadcast(&_cond);
 
-       if (result != 0)
-               vm_abort_errnum(result, "Condition::broadcast(): pthread_cond_broadcast failed");
+       if (result != 0) {
+               os::abort_errnum(result, "Condition::broadcast(): pthread_cond_broadcast failed");
+       }
 }
 
 
@@ -103,12 +111,11 @@ inline void Condition::broadcast()
  */
 inline void Condition::signal()
 {
-       int result;
+       int result = pthread_cond_signal(&_cond);
 
-       result = pthread_cond_signal(&_cond);
-
-       if (result != 0)
-               vm_abort_errnum(result, "Condition::signal(): pthread_cond_signal failed");
+       if (result != 0) {
+               os::abort_errnum(result, "Condition::signal(): pthread_cond_signal failed");
+       }
 }
 
 
@@ -128,12 +135,20 @@ inline void Condition::timedwait(Mutex* mutex, const struct timespec* abstime)
  */
 inline void Condition::wait(Mutex* mutex)
 {
-       int result;
+       wait(*mutex);
+}
 
-       result = pthread_cond_wait(&_cond, &(mutex->_mutex));
 
-       if (result != 0)
-               vm_abort_errnum(result, "Condition::wait(): pthread_cond_wait failed");
+/**
+ * Waits for the condition variable.
+ */
+inline void Condition::wait(Mutex& mutex)
+{
+       int result = pthread_cond_wait(&_cond, &(mutex._mutex));
+
+       if (result != 0) {
+               os::abort_errnum(result, "Condition::wait(): pthread_cond_wait failed");
+       }
 }
 
 #else
diff --git a/src/threads/posix/lock.c b/src/threads/posix/lock.c
deleted file mode 100644 (file)
index 81c3633..0000000
+++ /dev/null
@@ -1,1614 +0,0 @@
-/* src/threads/posix/lock.c - lock implementation
-
-   Copyright (C) 1996-2005, 2006, 2007, 2008
-   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
-
-   This file is part of CACAO.
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2, or (at
-   your option) any later version.
-
-   This program is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-   02110-1301, USA.
-
-*/
-
-
-#include "config.h"
-
-#include <assert.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/time.h>
-#include <pthread.h>
-
-#include "vm/types.h"
-
-#include "mm/memory.h"
-
-#include "native/llni.h"
-
-#include "threads/lock-common.h"
-#include "threads/mutex.hpp"
-#include "threads/threadlist.h"
-#include "threads/thread.hpp"
-
-#include "threads/posix/lock.h"
-
-#include "toolbox/list.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"
-
-#if defined(ENABLE_STATISTICS)
-# include "vm/statistics.h"
-#endif
-
-#if defined(ENABLE_VMLOG)
-#include <vmlog_cacao.h>
-#endif
-
-/* arch.h must be here because it defines USE_FAKE_ATOMIC_INSTRUCTIONS */
-
-#include "arch.h"
-
-/* includes for atomic instructions: */
-
-#if defined(USE_FAKE_ATOMIC_INSTRUCTIONS)
-#include "threads/posix/generic-primitives.h"
-#else
-#include "threads/atomic.hpp"
-#endif
-
-#if defined(ENABLE_JVMTI)
-#include "native/jvmti/cacaodbg.h"
-#endif
-
-#if defined(ENABLE_GC_BOEHM)
-# include "mm/boehm-gc/include/gc.h"
-#endif
-
-
-/* debug **********************************************************************/
-
-#if !defined(NDEBUG)
-# define DEBUGLOCKS(format) \
-    do { \
-        if (opt_DebugLocks) { \
-            log_println format; \
-        } \
-    } while (0)
-#else
-# define DEBUGLOCKS(format)
-#endif
-
-
-/******************************************************************************/
-/* MACROS                                                                     */
-/******************************************************************************/
-
-/* number of lock records in the first pool allocated for a thread */
-#define LOCK_INITIAL_LOCK_RECORDS 8
-
-#define LOCK_INITIAL_HASHTABLE_SIZE  1613  /* a prime in the middle between 1024 and 2048 */
-
-
-/******************************************************************************/
-/* MACROS FOR THIN/FAT LOCKS                                                  */
-/******************************************************************************/
-
-/* We use a variant of the tasuki locks described in the paper
- *     
- *     Tamiya Onodera, Kiyokuni Kawachiya
- *     A Study of Locking Objects with Bimodal Fields
- *     Proceedings of the ACM OOPSLA '99, pp. 223-237
- *     1999
- *
- * The underlying thin locks are a variant of the thin locks described in
- * 
- *     Bacon, Konuru, Murthy, Serrano
- *     Thin Locks: Featherweight Synchronization for Java
- *        Proceedings of the ACM Conference on Programming Language Design and 
- *        Implementation (Montreal, Canada), SIGPLAN Notices volume 33, number 6,
- *        June 1998
- *
- * In thin lock mode the lockword looks like this:
- *
- *     ,----------------------,-----------,---,
- *     |      thread ID       |   count   | 0 |
- *     `----------------------'-----------'---'
- *
- *     thread ID......the 'index' of the owning thread, or 0
- *     count..........number of times the lock has been entered        minus 1
- *     0..............the shape bit is 0 in thin lock mode
- *
- * In fat lock mode it is basically a lock_record_t *:
- *
- *     ,----------------------------------,---,
- *     |    lock_record_t * (without LSB) | 1 |
- *     `----------------------------------'---'
- *
- *     1..............the shape bit is 1 in fat lock mode
- */
-
-#if SIZEOF_VOID_P == 8
-#define THIN_LOCK_WORD_SIZE    64
-#else
-#define THIN_LOCK_WORD_SIZE    32
-#endif
-
-#define THIN_LOCK_SHAPE_BIT    0x01
-
-#define THIN_UNLOCKED          0
-
-#define THIN_LOCK_COUNT_SHIFT  1
-#define THIN_LOCK_COUNT_SIZE   8
-#define THIN_LOCK_COUNT_INCR   (1 << THIN_LOCK_COUNT_SHIFT)
-#define THIN_LOCK_COUNT_MAX    ((1 << THIN_LOCK_COUNT_SIZE) - 1)
-#define THIN_LOCK_COUNT_MASK   (THIN_LOCK_COUNT_MAX << THIN_LOCK_COUNT_SHIFT)
-
-#define THIN_LOCK_TID_SHIFT    (THIN_LOCK_COUNT_SIZE + THIN_LOCK_COUNT_SHIFT)
-#define THIN_LOCK_TID_SIZE     (THIN_LOCK_WORD_SIZE - THIN_LOCK_TID_SHIFT)
-
-#define IS_THIN_LOCK(lockword)  (!((lockword) & THIN_LOCK_SHAPE_BIT))
-#define IS_FAT_LOCK(lockword)     ((lockword) & THIN_LOCK_SHAPE_BIT)
-
-#define GET_FAT_LOCK(lockword)  ((lock_record_t *) ((lockword) & ~THIN_LOCK_SHAPE_BIT))
-#define MAKE_FAT_LOCK(ptr)      ((uintptr_t) (ptr) | THIN_LOCK_SHAPE_BIT)
-
-#define LOCK_WORD_WITHOUT_COUNT(lockword) ((lockword) & ~THIN_LOCK_COUNT_MASK)
-#define GET_THREAD_INDEX(lockword) ((unsigned) lockword >> THIN_LOCK_TID_SHIFT)
-
-
-/* global variables ***********************************************************/
-
-/* hashtable mapping objects to lock records */
-static lock_hashtable_t lock_hashtable;
-
-
-/******************************************************************************/
-/* PROTOTYPES                                                                 */
-/******************************************************************************/
-
-static void lock_hashtable_init(void);
-
-static inline uintptr_t lock_lockword_get(threadobject *t, java_handle_t *o);
-static inline void lock_lockword_set(threadobject *t, java_handle_t *o, uintptr_t lockword);
-static void lock_record_enter(threadobject *t, lock_record_t *lr);
-static void lock_record_exit(threadobject *t, lock_record_t *lr);
-static bool lock_record_wait(threadobject *t, lock_record_t *lr, s8 millis, s4 nanos);
-static void lock_record_notify(threadobject *t, lock_record_t *lr, bool one);
-
-
-/*============================================================================*/
-/* INITIALIZATION OF DATA STRUCTURES                                          */
-/*============================================================================*/
-
-
-/* lock_init *******************************************************************
-
-   Initialize global data for locking.
-
-*******************************************************************************/
-
-void lock_init(void)
-{
-       /* initialize lock hashtable */
-
-       lock_hashtable_init();
-
-#if defined(ENABLE_VMLOG)
-       vmlog_cacao_init_lock();
-#endif
-}
-
-
-/* lock_pre_compute_thinlock ***************************************************
-
-   Pre-compute the thin lock value for a thread index.
-
-   IN:
-      index........the thead index (>= 1)
-
-   RETURN VALUE:
-      the thin lock value for this thread index
-
-*******************************************************************************/
-
-ptrint lock_pre_compute_thinlock(s4 index)
-{
-       return (index << THIN_LOCK_TID_SHIFT) | THIN_UNLOCKED;
-}
-
-
-/* lock_record_new *************************************************************
-
-   Allocate a lock record.
-
-*******************************************************************************/
-
-static lock_record_t *lock_record_new(void)
-{
-       lock_record_t *lr;
-
-       /* allocate the data structure on the C heap */
-
-       lr = NEW(lock_record_t);
-
-#if defined(ENABLE_STATISTICS)
-       if (opt_stat)
-               size_lock_record += sizeof(lock_record_t);
-#endif
-
-       /* initialize the members */
-
-       lr->object  = NULL;
-       lr->owner   = NULL;
-       lr->count   = 0;
-       lr->waiters = list_create(OFFSET(lock_waiter_t, linkage));
-
-#if defined(ENABLE_GC_CACAO)
-       /* register the lock object as weak reference with the GC */
-
-       gc_weakreference_register(&(lr->object), GC_REFTYPE_LOCKRECORD);
-#endif
-
-       /* initialize the mutex */
-
-       lr->mutex = Mutex_new();
-
-       DEBUGLOCKS(("[lock_record_new   : lr=%p]", (void *) lr));
-
-       return lr;
-}
-
-
-/* lock_record_free ************************************************************
-
-   Free a lock record.
-
-   IN:
-       lr....lock record to free
-
-*******************************************************************************/
-
-static void lock_record_free(lock_record_t *lr)
-{
-       DEBUGLOCKS(("[lock_record_free  : lr=%p]", (void *) lr));
-
-       /* Destroy the mutex. */
-
-       Mutex_delete(lr->mutex);
-
-#if defined(ENABLE_GC_CACAO)
-       /* unregister the lock object reference with the GC */
-
-       gc_weakreference_unregister(&(lr->object));
-#endif
-
-       /* Free the waiters list. */
-
-       list_free(lr->waiters);
-
-       /* Free the data structure. */
-
-       FREE(lr, lock_record_t);
-
-#if defined(ENABLE_STATISTICS)
-       if (opt_stat)
-               size_lock_record -= sizeof(lock_record_t);
-#endif
-}
-
-
-/*============================================================================*/
-/* HASHTABLE MAPPING OBJECTS TO LOCK RECORDS                                  */
-/*============================================================================*/
-
-/* lock_hashtable_init *********************************************************
-
-   Initialize the global hashtable mapping objects to lock records.
-
-*******************************************************************************/
-
-static void lock_hashtable_init(void)
-{
-       lock_hashtable.mutex = Mutex_new();
-
-       lock_hashtable.size    = LOCK_INITIAL_HASHTABLE_SIZE;
-       lock_hashtable.entries = 0;
-       lock_hashtable.ptr     = MNEW(lock_record_t *, lock_hashtable.size);
-
-#if defined(ENABLE_STATISTICS)
-       if (opt_stat)
-               size_lock_hashtable += sizeof(lock_record_t *) * lock_hashtable.size;
-#endif
-
-       MZERO(lock_hashtable.ptr, lock_record_t *, lock_hashtable.size);
-}
-
-
-/* lock_hashtable_grow *********************************************************
-
-   Grow the lock record hashtable to about twice its current size and
-   rehash the entries.
-
-*******************************************************************************/
-
-/* must be called with hashtable mutex locked */
-static void lock_hashtable_grow(void)
-{
-       u4 oldsize;
-       u4 newsize;
-       lock_record_t **oldtable;
-       lock_record_t **newtable;
-       lock_record_t *lr;
-       lock_record_t *next;
-       u4 i;
-       u4 h;
-       u4 newslot;
-
-       /* allocate a new table */
-
-       oldsize = lock_hashtable.size;
-       newsize = oldsize*2 + 1; /* XXX should use prime numbers */
-
-       DEBUGLOCKS(("growing lock hashtable to size %d", newsize));
-
-       oldtable = lock_hashtable.ptr;
-       newtable = MNEW(lock_record_t *, newsize);
-
-#if defined(ENABLE_STATISTICS)
-       if (opt_stat)
-               size_lock_hashtable += sizeof(lock_record_t *) * newsize;
-#endif
-
-       MZERO(newtable, lock_record_t *, newsize);
-
-       /* rehash the entries */
-
-       for (i = 0; i < oldsize; i++) {
-               lr = oldtable[i];
-               while (lr) {
-                       next = lr->hashlink;
-
-                       h = heap_hashcode(lr->object);
-                       newslot = h % newsize;
-
-                       lr->hashlink = newtable[newslot];
-                       newtable[newslot] = lr;
-
-                       lr = next;
-               }
-       }
-
-       /* replace the old table */
-
-       lock_hashtable.ptr  = newtable;
-       lock_hashtable.size = newsize;
-
-       MFREE(oldtable, lock_record_t *, oldsize);
-
-#if defined(ENABLE_STATISTICS)
-       if (opt_stat)
-               size_lock_hashtable -= sizeof(lock_record_t *) * oldsize;
-#endif
-}
-
-
-/* lock_hashtable_cleanup ******************************************************
-
-   Removes (and frees) lock records which have a cleared object reference
-   from the hashtable. The locked object was reclaimed by the GC.
-
-*******************************************************************************/
-
-#if defined(ENABLE_GC_CACAO)
-void lock_hashtable_cleanup(void)
-{
-       threadobject  *t;
-       lock_record_t *lr;
-       lock_record_t *prev;
-       lock_record_t *next;
-       int i;
-
-       t = THREADOBJECT;
-
-       /* lock the hashtable */
-
-       Mutex_lock(lock_hashtable.mutex);
-
-       /* search the hashtable for cleared references */
-
-       for (i = 0; i < lock_hashtable.size; i++) {
-               lr = lock_hashtable.ptr[i];
-               prev = NULL;
-
-               while (lr) {
-                       next = lr->hashlink;
-
-                       /* remove lock records with cleared references */
-
-                       if (lr->object == NULL) {
-
-                               /* unlink the lock record from the hashtable */
-
-                               if (prev == NULL)
-                                       lock_hashtable.ptr[i] = next;
-                               else
-                                       prev->hashlink = next;
-
-                               /* free the lock record */
-
-                               lock_record_free(lr);
-
-                       } else {
-                               prev = lr;
-                       }
-
-                       lr = next;
-               }
-       }
-
-       /* unlock the hashtable */
-
-       Mutex_unlock(lock_hashtable.mutex);
-}
-#endif
-
-
-/* lock_hashtable_get **********************************************************
-
-   Find the lock record for the given object.  If it does not exists,
-   yet, create it and enter it in the hashtable.
-
-   IN:
-      t....the current thread
-         o....the object to look up
-
-   RETURN VALUE:
-      the lock record to use for this object
-
-*******************************************************************************/
-
-#if defined(ENABLE_GC_BOEHM)
-static void lock_record_finalizer(void *object, void *p);
-#endif
-
-static lock_record_t *lock_hashtable_get(threadobject *t, java_handle_t *o)
-{
-       uintptr_t      lockword;
-       u4             slot;
-       lock_record_t *lr;
-
-       lockword = lock_lockword_get(t, o);
-
-       if (IS_FAT_LOCK(lockword))
-               return GET_FAT_LOCK(lockword);
-
-       /* lock the hashtable */
-
-       Mutex_lock(lock_hashtable.mutex);
-
-       /* lookup the lock record in the hashtable */
-
-       LLNI_CRITICAL_START_THREAD(t);
-       slot = heap_hashcode(LLNI_DIRECT(o)) % lock_hashtable.size;
-       lr   = lock_hashtable.ptr[slot];
-
-       for (; lr != NULL; lr = lr->hashlink) {
-               if (lr->object == LLNI_DIRECT(o))
-                       break;
-       }
-       LLNI_CRITICAL_END_THREAD(t);
-
-       if (lr == NULL) {
-               /* not found, we must create a new one */
-
-               lr = lock_record_new();
-
-               LLNI_CRITICAL_START_THREAD(t);
-               lr->object = LLNI_DIRECT(o);
-               LLNI_CRITICAL_END_THREAD(t);
-
-#if defined(ENABLE_GC_BOEHM)
-               /* register new finalizer to clean up the lock record */
-
-               GC_REGISTER_FINALIZER(LLNI_DIRECT(o), lock_record_finalizer, 0, 0, 0);
-#endif
-
-               /* enter it in the hashtable */
-
-               lr->hashlink             = lock_hashtable.ptr[slot];
-               lock_hashtable.ptr[slot] = lr;
-               lock_hashtable.entries++;
-
-               /* check whether the hash should grow */
-
-               if (lock_hashtable.entries * 3 > lock_hashtable.size * 4) {
-                       lock_hashtable_grow();
-               }
-       }
-
-       /* unlock the hashtable */
-
-       Mutex_unlock(lock_hashtable.mutex);
-
-       /* return the new lock record */
-
-       return lr;
-}
-
-
-/* lock_hashtable_remove *******************************************************
-
-   Remove the lock record for the given object from the hashtable
-   and free it afterwards.
-
-   IN:
-       t....the current thread
-       o....the object to look up
-
-*******************************************************************************/
-
-static void lock_hashtable_remove(threadobject *t, java_handle_t *o)
-{
-       uintptr_t      lockword;
-       lock_record_t *lr;
-       u4             slot;
-       lock_record_t *tmplr;
-
-       /* lock the hashtable */
-
-       Mutex_lock(lock_hashtable.mutex);
-
-       /* get lock record */
-
-       lockword = lock_lockword_get(t, o);
-
-       assert(IS_FAT_LOCK(lockword));
-
-       lr = GET_FAT_LOCK(lockword);
-
-       /* remove the lock-record from the hashtable */
-
-       LLNI_CRITICAL_START_THREAD(t);
-       slot  = heap_hashcode(LLNI_DIRECT(o)) % lock_hashtable.size;
-       tmplr = lock_hashtable.ptr[slot];
-       LLNI_CRITICAL_END_THREAD(t);
-
-       if (tmplr == lr) {
-               /* special handling if it's the first in the chain */
-
-               lock_hashtable.ptr[slot] = lr->hashlink;
-       }
-       else {
-               for (; tmplr != NULL; tmplr = tmplr->hashlink) {
-                       if (tmplr->hashlink == lr) {
-                               tmplr->hashlink = lr->hashlink;
-                               break;
-                       }
-               }
-
-               assert(tmplr != NULL);
-       }
-
-       /* decrease entry count */
-
-       lock_hashtable.entries--;
-
-       /* unlock the hashtable */
-
-       Mutex_unlock(lock_hashtable.mutex);
-
-       /* free the lock record */
-
-       lock_record_free(lr);
-}
-
-
-/* lock_record_finalizer *******************************************************
-
-   XXX Remove me for exact GC.
-
-*******************************************************************************/
-
-static void lock_record_finalizer(void *object, void *p)
-{
-       java_handle_t *o;
-       classinfo     *c;
-
-       o = (java_handle_t *) object;
-
-#if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
-       /* XXX this is only a dirty hack to make Boehm work with handles */
-
-       o = LLNI_WRAP((java_object_t *) o);
-#endif
-
-       LLNI_class_get(o, c);
-
-#if !defined(NDEBUG)
-       if (opt_DebugFinalizer) {
-               log_start();
-               log_print("[finalizer lockrecord: o=%p p=%p class=", object, p);
-               class_print(c);
-               log_print("]");
-               log_finish();
-       }
-#endif
-
-       /* check for a finalizer function */
-
-       if (c->finalizer != NULL)
-               finalizer_run(object, p);
-
-       /* remove the lock-record entry from the hashtable and free it */
-
-       lock_hashtable_remove(THREADOBJECT, o);
-}
-
-
-/*============================================================================*/
-/* OBJECT LOCK INITIALIZATION                                                 */
-/*============================================================================*/
-
-
-/* lock_init_object_lock *******************************************************
-
-   Initialize the monitor pointer of the given object. The monitor gets
-   initialized to an unlocked state.
-
-*******************************************************************************/
-
-void lock_init_object_lock(java_object_t *o)
-{
-       assert(o);
-
-       o->lockword = THIN_UNLOCKED;
-}
-
-
-/*============================================================================*/
-/* LOCKING ALGORITHM                                                          */
-/*============================================================================*/
-
-
-/* lock_lockword_get ***********************************************************
-
-   Get the lockword for the given object.
-
-   IN:
-      t............the current thread
-      o............the object
-
-*******************************************************************************/
-
-static inline uintptr_t lock_lockword_get(threadobject *t, java_handle_t *o)
-{
-       uintptr_t lockword;
-
-       LLNI_CRITICAL_START_THREAD(t);
-       lockword = LLNI_DIRECT(o)->lockword;
-       LLNI_CRITICAL_END_THREAD(t);
-
-       return lockword;
-}
-
-
-/* lock_lockword_set ***********************************************************
-
-   Set the lockword for the given object.
-
-   IN:
-      t............the current thread
-      o............the object
-         lockword.....the new lockword value
-
-*******************************************************************************/
-
-static inline void lock_lockword_set(threadobject *t, java_handle_t *o, uintptr_t lockword)
-{
-       LLNI_CRITICAL_START_THREAD(t);
-       LLNI_DIRECT(o)->lockword = lockword;
-       LLNI_CRITICAL_END_THREAD(t);
-}
-
-
-/* lock_record_enter ***********************************************************
-
-   Enter the lock represented by the given lock record.
-
-   IN:
-      t.................the current thread
-         lr................the lock record
-
-*******************************************************************************/
-
-static inline void lock_record_enter(threadobject *t, lock_record_t *lr)
-{
-       Mutex_lock(lr->mutex);
-       lr->owner = t;
-}
-
-
-/* lock_record_exit ************************************************************
-
-   Release the lock represented by the given lock record.
-
-   IN:
-      t.................the current thread
-         lr................the lock record
-
-   PRE-CONDITION:
-      The current thread must own the lock represented by this lock record.
-         This is NOT checked by this function!
-
-*******************************************************************************/
-
-static inline void lock_record_exit(threadobject *t, lock_record_t *lr)
-{
-       lr->owner = NULL;
-       Mutex_unlock(lr->mutex);
-}
-
-
-/* lock_inflate ****************************************************************
-
-   Inflate the lock of the given object. This may only be called by the
-   owner of the monitor of the object.
-
-   IN:
-      t............the current thread
-         o............the object of which to inflate the lock
-         lr...........the lock record to install. The current thread must
-                      own the lock of this lock record!
-
-   PRE-CONDITION:
-      The current thread must be the owner of this object's monitor AND
-         of the lock record's lock!
-
-*******************************************************************************/
-
-static void lock_inflate(threadobject *t, java_handle_t *o, lock_record_t *lr)
-{
-       uintptr_t lockword;
-
-       /* get the current lock count */
-
-       lockword = lock_lockword_get(t, o);
-
-       if (IS_FAT_LOCK(lockword)) {
-               assert(GET_FAT_LOCK(lockword) == lr);
-               return;
-       }
-       else {
-               assert(LOCK_WORD_WITHOUT_COUNT(lockword) == t->thinlock);
-
-               /* copy the count from the thin lock */
-
-               lr->count = (lockword & THIN_LOCK_COUNT_MASK) >> THIN_LOCK_COUNT_SHIFT;
-       }
-
-       DEBUGLOCKS(("[lock_inflate      : lr=%p, t=%p, o=%p, o->lockword=%lx, count=%d]",
-                               lr, t, o, lockword, lr->count));
-
-       /* install it */
-
-       lock_lockword_set(t, o, MAKE_FAT_LOCK(lr));
-}
-
-
-/* TODO Move this function into threadlist.[ch]. */
-
-static threadobject *threads_lookup_thread_id(int index)
-{
-       threadobject *t;
-
-       threadlist_lock();
-
-       for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
-               if (t->state == THREAD_STATE_NEW)
-                       continue;
-               if (t->index == index)
-                       break;
-       }
-
-       threadlist_unlock();
-       return t;
-}
-
-static void sable_flc_waiting(ptrint lockword, threadobject *t, java_handle_t *o)
-{
-       int index;
-       threadobject *t_other;
-       int old_flc;
-
-       index = GET_THREAD_INDEX(lockword);
-       t_other = threads_lookup_thread_id(index);
-       if (!t_other)
-/*             failure, TODO: add statistics */
-               return;
-
-       Mutex_lock(t_other->flc_lock);
-       old_flc = t_other->flc_bit;
-       t_other->flc_bit = true;
-
-       DEBUGLOCKS(("thread %d set flc bit for lock-holding thread %d",
-                               t->index, t_other->index));
-
-       /* Set FLC bit first, then read the lockword again */
-       Atomic_memory_barrier();
-
-       lockword = lock_lockword_get(t, o);
-
-       /* Lockword is still the way it was seen before */
-       if (IS_THIN_LOCK(lockword) && (GET_THREAD_INDEX(lockword) == index))
-       {
-               /* Add tuple (t, o) to the other thread's FLC list */
-               t->flc_object = o;
-               t->flc_next = t_other->flc_list;
-               t_other->flc_list = t;
-
-               for (;;)
-               {
-                       threadobject *current;
-
-                       /* Wait until another thread sees the flc bit and notifies
-                          us of unlocking. */
-                       Condition_wait(t->flc_cond, t_other->flc_lock);
-
-                       /* Traverse FLC list looking if we're still there */
-                       current = t_other->flc_list;
-                       while (current && current != t)
-                               current = current->flc_next;
-                       if (!current)
-                               /* not in list anymore, can stop waiting */
-                               break;
-
-                       /* We are still in the list -- the other thread cannot have seen
-                          the FLC bit yet */
-                       assert(t_other->flc_bit);
-               }
-
-               t->flc_object = NULL;   /* for garbage collector? */
-               t->flc_next = NULL;
-       }
-       else
-               t_other->flc_bit = old_flc;
-
-       Mutex_unlock(t_other->flc_lock);
-}
-
-static void notify_flc_waiters(threadobject *t, java_handle_t *o)
-{
-       threadobject *current;
-
-       Mutex_lock(t->flc_lock);
-
-       current = t->flc_list;
-       while (current)
-       {
-               if (current->flc_object != o)
-               {
-                       /* The object has to be inflated so the other threads can properly
-                          block on it. */
-
-                       /* Only if not already inflated */
-                       ptrint lockword = lock_lockword_get(t, current->flc_object);
-                       if (IS_THIN_LOCK(lockword)) {
-                               lock_record_t *lr = lock_hashtable_get(t, current->flc_object);
-                               lock_record_enter(t, lr);
-
-                               DEBUGLOCKS(("thread %d inflating lock of %p to lr %p",
-                                                       t->index, (void*) current->flc_object, (void*) lr));
-
-                               lock_inflate(t, current->flc_object, lr);
-                       }
-               }
-               /* Wake the waiting thread */
-               Condition_broadcast(current->flc_cond);
-
-               current = current->flc_next;
-       }
-
-       t->flc_list = NULL;
-       t->flc_bit = false;
-       Mutex_unlock(t->flc_lock);
-}
-
-/* lock_monitor_enter **********************************************************
-
-   Acquire the monitor of the given object. If the current thread already
-   owns the monitor, the lock counter is simply increased.
-
-   This function blocks until it can acquire the monitor.
-
-   IN:
-      t............the current thread
-         o............the object of which to enter the monitor
-
-   RETURN VALUE:
-      true.........the lock has been successfully acquired
-         false........an exception has been thrown
-
-*******************************************************************************/
-
-bool lock_monitor_enter(java_handle_t *o)
-{
-       threadobject  *t;
-       /* CAUTION: This code assumes that ptrint is unsigned! */
-       ptrint         lockword;
-       ptrint         thinlock;
-       lock_record_t *lr;
-
-       if (o == NULL) {
-               exceptions_throw_nullpointerexception();
-               return false;
-       }
-
-       t = THREADOBJECT;
-
-       thinlock = t->thinlock;
-
-retry:
-       /* most common case: try to thin-lock an unlocked object */
-
-       LLNI_CRITICAL_START_THREAD(t);
-       lockword = Atomic_compare_and_swap_ptr(&(LLNI_DIRECT(o)->lockword), THIN_UNLOCKED, thinlock);
-       LLNI_CRITICAL_END_THREAD(t);
-
-       if (lockword == THIN_UNLOCKED) {
-               /* success. we locked it */
-               /* The Java Memory Model requires a memory barrier here: */
-               /* Because of the CAS above, this barrier is a nop on x86 / x86_64 */
-               Atomic_instruction_barrier();
-               return true;
-       }
-
-       /* next common case: recursive lock with small recursion count */
-       /* We don't have to worry about stale values here, as any stale value  */
-       /* will indicate another thread holding the lock (or an inflated lock) */
-
-       if (LOCK_WORD_WITHOUT_COUNT(lockword) == thinlock) {
-               /* we own this monitor               */
-               /* check the current recursion count */
-
-               if ((lockword ^ thinlock) < (THIN_LOCK_COUNT_MAX << THIN_LOCK_COUNT_SHIFT))
-               {
-                       /* the recursion count is low enough */
-
-                       lock_lockword_set(t, o, lockword + THIN_LOCK_COUNT_INCR);
-
-                       /* success. we locked it */
-                       return true;
-               }
-               else {
-                       /* recursion count overflow */
-
-                       lr = lock_hashtable_get(t, o);
-                       lock_record_enter(t, lr);
-                       lock_inflate(t, o, lr);
-                       lr->count++;
-
-                       notify_flc_waiters(t, o);
-
-                       return true;
-               }
-       }
-
-       /* the lock is either contented or fat */
-
-       if (IS_FAT_LOCK(lockword)) {
-
-               lr = GET_FAT_LOCK(lockword);
-
-               /* check for recursive entering */
-               if (lr->owner == t) {
-                       lr->count++;
-                       return true;
-               }
-
-               /* acquire the mutex of the lock record */
-
-               lock_record_enter(t, lr);
-
-               assert(lr->count == 0);
-
-               return true;
-       }
-
-       /****** inflation path ******/
-
-#if defined(ENABLE_JVMTI)
-       /* Monitor Contended Enter */
-       jvmti_MonitorContendedEntering(false, o);
-#endif
-
-       sable_flc_waiting(lockword, t, o);
-
-#if defined(ENABLE_JVMTI)
-       /* Monitor Contended Entered */
-       jvmti_MonitorContendedEntering(true, o);
-#endif
-       goto retry;
-}
-
-
-/* lock_monitor_exit ***********************************************************
-
-   Decrement the counter of a (currently owned) monitor. If the counter
-   reaches zero, release the monitor.
-
-   If the current thread is not the owner of the monitor, an 
-   IllegalMonitorState exception is thrown.
-
-   IN:
-      t............the current thread
-         o............the object of which to exit the monitor
-
-   RETURN VALUE:
-      true.........everything ok,
-         false........an exception has been thrown
-
-*******************************************************************************/
-
-bool lock_monitor_exit(java_handle_t *o)
-{
-       threadobject *t;
-       uintptr_t     lockword;
-       ptrint        thinlock;
-
-       if (o == NULL) {
-               exceptions_throw_nullpointerexception();
-               return false;
-       }
-
-       t = THREADOBJECT;
-
-       thinlock = t->thinlock;
-
-       /* We don't have to worry about stale values here, as any stale value */
-       /* will indicate that we don't own the lock.                          */
-
-       lockword = lock_lockword_get(t, o);
-
-       /* most common case: we release a thin lock that we hold once */
-
-       if (lockword == thinlock) {
-               /* memory barrier for Java Memory Model */
-               Atomic_write_memory_barrier();
-               lock_lockword_set(t, o, THIN_UNLOCKED);
-               /* Memory barrier for thin locking. */
-               Atomic_memory_barrier();
-
-               /* check if there has been a flat lock contention on this object */
-
-               if (t->flc_bit) {
-                       DEBUGLOCKS(("thread %d saw flc bit", t->index));
-
-                       /* there has been a contention on this thin lock */
-                       notify_flc_waiters(t, o);
-               }
-
-               return true;
-       }
-
-       /* next common case: we release a recursive lock, count > 0 */
-
-       if (LOCK_WORD_WITHOUT_COUNT(lockword) == thinlock) {
-               lock_lockword_set(t, o, lockword - THIN_LOCK_COUNT_INCR);
-               return true;
-       }
-
-       /* either the lock is fat, or we don't hold it at all */
-
-       if (IS_FAT_LOCK(lockword)) {
-
-               lock_record_t *lr;
-
-               lr = GET_FAT_LOCK(lockword);
-
-               /* check if we own this monitor */
-               /* We don't have to worry about stale values here, as any stale value */
-               /* will be != t and thus fail this check.                             */
-
-               if (lr->owner != t) {
-                       exceptions_throw_illegalmonitorstateexception();
-                       return false;
-               }
-
-               /* { the current thread `t` owns the lock record `lr` on object `o` } */
-
-               if (lr->count != 0) {
-                       /* we had locked this one recursively. just decrement, it will */
-                       /* still be locked. */
-                       lr->count--;
-                       return true;
-               }
-
-               /* unlock this lock record */
-
-               lr->owner = NULL;
-               Mutex_unlock(lr->mutex);
-
-               return true;
-       }
-
-       /* legal thin lock cases have been handled above, so this is an error */
-
-       exceptions_throw_illegalmonitorstateexception();
-
-       return false;
-}
-
-
-/* lock_record_add_waiter ******************************************************
-
-   Add a thread to the list of waiting threads of a lock record.
-
-   IN:
-      lr...........the lock record
-      thread.......the thread to add
-
-*******************************************************************************/
-
-static void lock_record_add_waiter(lock_record_t *lr, threadobject *thread)
-{
-       lock_waiter_t *w;
-
-       /* Allocate a waiter data structure. */
-
-       w = NEW(lock_waiter_t);
-
-#if defined(ENABLE_STATISTICS)
-       if (opt_stat)
-               size_lock_waiter += sizeof(lock_waiter_t);
-#endif
-
-       /* Store the thread in the waiter structure. */
-
-       w->thread = thread;
-
-       /* Add the waiter as last entry to waiters list. */
-
-       list_add_last(lr->waiters, w);
-}
-
-
-/* lock_record_remove_waiter ***************************************************
-
-   Remove a thread from the list of waiting threads of a lock record.
-
-   IN:
-      lr...........the lock record
-      t............the current thread
-
-   PRE-CONDITION:
-      The current thread must be the owner of the lock record.
-   
-*******************************************************************************/
-
-static void lock_record_remove_waiter(lock_record_t *lr, threadobject *thread)
-{
-       list_t        *l;
-       lock_waiter_t *w;
-
-       /* Get the waiters list. */
-
-       l = lr->waiters;
-
-       for (w = list_first(l); w != NULL; w = list_next(l, w)) {
-               if (w->thread == thread) {
-                       /* Remove the waiter entry from the list. */
-
-                       list_remove(l, w);
-
-                       /* Free the waiter data structure. */
-
-                       FREE(w, lock_waiter_t);
-
-#if defined(ENABLE_STATISTICS)
-                       if (opt_stat)
-                               size_lock_waiter -= sizeof(lock_waiter_t);
-#endif
-
-                       return;
-               }
-       }
-
-       /* This should never happen. */
-
-       vm_abort("lock_record_remove_waiter: thread not found in list of waiters\n");
-}
-
-
-/* lock_record_wait ************************************************************
-
-   Wait on a lock record for a given (maximum) amount of time.
-
-   IN:
-      t............the current thread
-         lr...........the lock record
-         millis.......milliseconds of timeout
-         nanos........nanoseconds of timeout
-
-   RETURN VALUE:
-      true.........we have been interrupted,
-      false........everything ok
-
-   PRE-CONDITION:
-      The current thread must be the owner of the lock record.
-         This is NOT checked by this function!
-   
-*******************************************************************************/
-
-static bool lock_record_wait(threadobject *thread, lock_record_t *lr, s8 millis, s4 nanos)
-{
-       s4   lockcount;
-       bool wasinterrupted = false;
-
-       DEBUGLOCKS(("[lock_record_wait  : lr=%p, t=%p, millis=%lld, nanos=%d]",
-                               lr, thread, millis, nanos));
-
-       /* { the thread t owns the fat lock record lr on the object o } */
-
-       /* register us as waiter for this object */
-
-       lock_record_add_waiter(lr, thread);
-
-       /* remember the old lock count */
-
-       lockcount = lr->count;
-
-       /* unlock this record */
-
-       lr->count = 0;
-       lock_record_exit(thread, lr);
-
-       /* wait until notified/interrupted/timed out */
-
-       threads_wait_with_timeout_relative(thread, millis, nanos);
-
-       /* re-enter the monitor */
-
-       lock_record_enter(thread, lr);
-
-       /* remove us from the list of waiting threads */
-
-       lock_record_remove_waiter(lr, thread);
-
-       /* restore the old lock count */
-
-       lr->count = lockcount;
-
-       /* We can only be signaled OR interrupted, not both. If both flags
-          are set, reset only signaled and leave the thread in
-          interrupted state. Otherwise, clear both. */
-
-       if (!thread->signaled) {
-               wasinterrupted = thread->interrupted;
-               thread->interrupted = false;
-       }
-
-       thread->signaled = false;
-
-       /* return if we have been interrupted */
-
-       return wasinterrupted;
-}
-
-
-/* lock_monitor_wait ***********************************************************
-
-   Wait on an object for a given (maximum) amount of time.
-
-   IN:
-      t............the current thread
-         o............the object
-         millis.......milliseconds of timeout
-         nanos........nanoseconds of timeout
-
-   PRE-CONDITION:
-      The current thread must be the owner of the object's monitor.
-   
-*******************************************************************************/
-
-static void lock_monitor_wait(threadobject *t, java_handle_t *o, s8 millis, s4 nanos)
-{
-       uintptr_t      lockword;
-       lock_record_t *lr;
-
-       lockword = lock_lockword_get(t, o);
-
-       /* check if we own this monitor */
-       /* We don't have to worry about stale values here, as any stale value */
-       /* will fail this check.                                              */
-
-       if (IS_FAT_LOCK(lockword)) {
-
-               lr = GET_FAT_LOCK(lockword);
-
-               if (lr->owner != t) {
-                       exceptions_throw_illegalmonitorstateexception();
-                       return;
-               }
-       }
-       else {
-               /* it's a thin lock */
-
-               if (LOCK_WORD_WITHOUT_COUNT(lockword) != t->thinlock) {
-                       exceptions_throw_illegalmonitorstateexception();
-                       return;
-               }
-
-               /* inflate this lock */
-
-               lr = lock_hashtable_get(t, o);
-               lock_record_enter(t, lr);
-               lock_inflate(t, o, lr);
-
-               notify_flc_waiters(t, o);
-       }
-
-       /* { the thread t owns the fat lock record lr on the object o } */
-
-       if (lock_record_wait(t, lr, millis, nanos))
-               exceptions_throw_interruptedexception();
-}
-
-
-/* lock_record_notify **********************************************************
-
-   Notify one thread or all threads waiting on the given lock record.
-
-   IN:
-      t............the current thread
-         lr...........the lock record
-         one..........if true, only notify one thread
-
-   PRE-CONDITION:
-      The current thread must be the owner of the lock record.
-         This is NOT checked by this function!
-   
-*******************************************************************************/
-
-static void lock_record_notify(threadobject *t, lock_record_t *lr, bool one)
-{
-       list_t        *l;
-       lock_waiter_t *w;
-       threadobject  *waitingthread;
-
-       /* { the thread t owns the fat lock record lr on the object o } */
-
-       /* Get the waiters list. */
-
-       l = lr->waiters;
-
-       for (w = list_first(l); w != NULL; w = list_next(l, w)) {
-               /* signal the waiting thread */
-
-               waitingthread = w->thread;
-
-               /* We must skip threads which have already been notified. They will
-                  remove themselves from the list. */
-
-               if (waitingthread->signaled)
-                       continue;
-
-               /* Enter the wait-mutex. */
-
-               Mutex_lock(waitingthread->waitmutex);
-
-               DEBUGLOCKS(("[lock_record_notify: lr=%p, t=%p, waitingthread=%p, one=%d]",
-                                       lr, t, waitingthread, one));
-
-               Condition_signal(waitingthread->waitcond);
-
-               /* Mark the thread as signaled. */
-
-               waitingthread->signaled = true;
-
-               /* Leave the wait-mutex. */
-
-               Mutex_unlock(waitingthread->waitmutex);
-
-               /* if we should only wake one, we are done */
-
-               if (one)
-                       break;
-       }
-}
-
-
-/* lock_monitor_notify *********************************************************
-
-   Notify one thread or all threads waiting on the given object.
-
-   IN:
-      t............the current thread
-         o............the object
-         one..........if true, only notify one thread
-
-   PRE-CONDITION:
-      The current thread must be the owner of the object's monitor.
-   
-*******************************************************************************/
-
-static void lock_monitor_notify(threadobject *t, java_handle_t *o, bool one)
-{
-       uintptr_t      lockword;
-       lock_record_t *lr;
-
-       lockword = lock_lockword_get(t, o);
-
-       /* check if we own this monitor */
-       /* We don't have to worry about stale values here, as any stale value */
-       /* will fail this check.                                              */
-
-       if (IS_FAT_LOCK(lockword)) {
-
-               lr = GET_FAT_LOCK(lockword);
-
-               if (lr->owner != t) {
-                       exceptions_throw_illegalmonitorstateexception();
-                       return;
-               }
-       }
-       else {
-               /* it's a thin lock */
-
-               if (LOCK_WORD_WITHOUT_COUNT(lockword) != t->thinlock) {
-                       exceptions_throw_illegalmonitorstateexception();
-                       return;
-               }
-
-               /* no thread can wait on a thin lock, so there's nothing to do. */
-               return;
-       }
-
-       /* { the thread t owns the fat lock record lr on the object o } */
-
-       lock_record_notify(t, lr, one);
-}
-
-
-
-/*============================================================================*/
-/* INQUIRY FUNCIONS                                                           */
-/*============================================================================*/
-
-
-/* lock_is_held_by_current_thread **********************************************
-
-   Return true if the current thread owns the monitor of the given object.
-
-   IN:
-         o............the object
-
-   RETURN VALUE:
-      true, if the current thread holds the lock of this object.
-   
-*******************************************************************************/
-
-bool lock_is_held_by_current_thread(java_handle_t *o)
-{
-       threadobject  *t;
-       uintptr_t      lockword;
-       lock_record_t *lr;
-
-       t = THREADOBJECT;
-
-       /* check if we own this monitor */
-       /* We don't have to worry about stale values here, as any stale value */
-       /* will fail this check.                                              */
-
-       lockword = lock_lockword_get(t, o);
-
-       if (IS_FAT_LOCK(lockword)) {
-               /* it's a fat lock */
-
-               lr = GET_FAT_LOCK(lockword);
-
-               return (lr->owner == t);
-       }
-       else {
-               /* it's a thin lock */
-
-               return (LOCK_WORD_WITHOUT_COUNT(lockword) == t->thinlock);
-       }
-}
-
-
-
-/*============================================================================*/
-/* WRAPPERS FOR OPERATIONS ON THE CURRENT THREAD                              */
-/*============================================================================*/
-
-
-/* lock_wait_for_object ********************************************************
-
-   Wait for the given object.
-
-   IN:
-         o............the object
-         millis.......milliseconds to wait
-         nanos........nanoseconds to wait
-   
-*******************************************************************************/
-
-void lock_wait_for_object(java_handle_t *o, s8 millis, s4 nanos)
-{
-       threadobject *thread;
-
-       thread = THREADOBJECT;
-
-       lock_monitor_wait(thread, o, millis, nanos);
-}
-
-
-/* lock_notify_object **********************************************************
-
-   Notify one thread waiting on the given object.
-
-   IN:
-         o............the object
-   
-*******************************************************************************/
-
-void lock_notify_object(java_handle_t *o)
-{
-       threadobject *thread;
-
-       thread = THREADOBJECT;
-
-       lock_monitor_notify(thread, o, true);
-}
-
-
-/* lock_notify_all_object ******************************************************
-
-   Notify all threads waiting on the given object.
-
-   IN:
-         o............the object
-   
-*******************************************************************************/
-
-void lock_notify_all_object(java_handle_t *o)
-{
-       threadobject *thread;
-
-       thread = THREADOBJECT;
-
-       lock_monitor_notify(thread, o, false);
-}
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
diff --git a/src/threads/posix/lock.h b/src/threads/posix/lock.h
deleted file mode 100644 (file)
index ddadd3f..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-/* src/threads/posix/lock.h - lock implementation
-
-   Copyright (C) 1996-2005, 2006, 2007, 2008
-   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
-
-   This file is part of CACAO.
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2, or (at
-   your option) any later version.
-
-   This program is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-   02110-1301, USA.
-
-*/
-
-
-#ifndef _LOCK_H
-#define _LOCK_H
-
-#include "config.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <pthread.h>
-
-#include "vm/types.h"
-
-#include "native/llni.h"
-
-#include "threads/mutex.hpp"
-
-#include "toolbox/list.h"
-
-#include "vm/global.h"
-
-
-
-/* typedefs *******************************************************************/
-
-typedef struct lock_record_t    lock_record_t;
-typedef struct lock_waiter_t    lock_waiter_t;
-typedef struct lock_hashtable_t lock_hashtable_t;
-
-
-/* lock_waiter_t ***************************************************************
-
-   List node for storing a waiting thread.
-
-*******************************************************************************/
-
-struct lock_waiter_t {
-       struct threadobject *thread;        /* the waiting thread                 */
-       listnode_t           linkage;
-};
-
-
-/* lock_record_t ***************************************************************
-
-   Lock record struct representing an inflated ("fat") lock.
-
-*******************************************************************************/
-
-struct lock_record_t {
-       java_object_t       *object;             /* object for which this lock is */
-       struct threadobject *owner;              /* current owner of this monitor */
-       s4                   count;              /* recursive lock count          */
-       Mutex*               mutex;              /* mutex for synchronizing       */
-       list_t              *waiters;            /* list of threads waiting       */
-       lock_record_t       *hashlink;           /* next record in hash chain     */
-};
-
-
-/* lock_hashtable_t ************************************************************
-   The global hashtable mapping objects to lock records.
-
-*******************************************************************************/
-
-struct lock_hashtable_t {
-    Mutex*               mutex;       /* mutex for synch. access to the table */
-       u4                   size;        /* number of slots                      */
-       u4                   entries;     /* current number of entries            */
-       lock_record_t      **ptr;         /* the table of slots, uses ext. chain. */
-};
-
-
-/* defines ********************************************************************/
-
-#define LOCK_INIT_OBJECT_LOCK(o) lock_init_object_lock((java_object_t *) (o))
-
-#define LOCK_MONITOR_ENTER(o)    lock_monitor_enter((java_handle_t *) LLNI_QUICKWRAP(o))
-#define LOCK_MONITOR_EXIT(o)     lock_monitor_exit((java_handle_t *) LLNI_QUICKWRAP(o))
-
-#define LOCK_WAIT_FOREVER(o)     lock_wait_for_object((java_handle_t *) LLNI_QUICKWRAP(o), 0, 0)
-#define LOCK_NOTIFY(o)           lock_notify_object((java_handle_t *) LLNI_QUICKWRAP(o))
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _LOCK_H */
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
index 3a262aea050346b9105cd0325768e2932dab6f75..e7206d5f51a8553f065db5614310cef4c800786a 100644 (file)
@@ -2,6 +2,7 @@
 
    Copyright (C) 2008
    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+   Copyright (C) 2008 Theobroma Systems Ltd.
 
    This file is part of CACAO.
 
@@ -30,7 +31,6 @@
 
 #include <pthread.h>
 
-#include "vm/vm.hpp"
 
 #ifdef __cplusplus
 
 class Mutex {
 private:
        // POSIX mutex structure.
-       pthread_mutex_t _mutex;
+       pthread_mutex_t     _mutex;
+       pthread_mutexattr_t _attr;
 
        // Condition class needs to access _mutex for wait() and
        // timedwait().
        friend class Condition;
        
 public:
-       Mutex();
-       ~Mutex();
+       inline Mutex();
+       inline ~Mutex();
 
-       void lock();
-       void unlock();
+       inline void lock();
+       inline void unlock();
 };
 
+#else
+
+// Forward typedefs
+typedef struct Mutex Mutex;
+
+#endif
 
-/* static mutex initializer ***************************************************/
 
-#define MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
+// Includes.
+#include "vm/os.hpp"
 
 
+#ifdef __cplusplus
+
 /**
  * Initializes the given mutex object and checks for errors.
  */
 inline Mutex::Mutex()
 {
-       int result;
+       int result = pthread_mutexattr_init(&_attr);
+
+       if (result != 0) {
+               os::abort_errnum(result, "Mutex::Mutex(): pthread_mutexattr_init failed");
+       }
 
-       result = pthread_mutex_init(&_mutex, NULL);
+       result = pthread_mutexattr_settype(&_attr, PTHREAD_MUTEX_RECURSIVE);
 
-       if (result != 0)
-               vm_abort_errnum(result, "Mutex::Mutex(): pthread_mutex_init failed");
+       if (result != 0) {
+               os::abort_errnum(result, "Mutex::Mutex(): pthread_mutexattr_settype failed");
+       }
+
+       result = pthread_mutex_init(&_mutex, &_attr);
+
+       if (result != 0) {
+               os::abort_errnum(result, "Mutex::Mutex(): pthread_mutex_init failed");
+       }
 }
 
 
@@ -79,12 +99,17 @@ inline Mutex::Mutex()
  */
 inline Mutex::~Mutex()
 {
-       int result;
+       int result = pthread_mutexattr_destroy(&_attr);
+
+       if (result != 0) {
+               os::abort_errnum(result, "Mutex::~Mutex(): pthread_mutexattr_destroy failed");
+       }
 
        result = pthread_mutex_destroy(&_mutex);
 
-       if (result != 0)
-               vm_abort_errnum(result, "Mutex::~Mutex(): pthread_mutex_destroy failed");
+       if (result != 0) {
+               os::abort_errnum(result, "Mutex::~Mutex(): pthread_mutex_destroy failed");
+       }
 }
 
 
@@ -99,12 +124,11 @@ inline Mutex::~Mutex()
  */
 inline void Mutex::lock()
 {
-       int result;
+       int result = pthread_mutex_lock(&_mutex);
 
-       result = pthread_mutex_lock(&_mutex);
-
-       if (result != 0)
-               vm_abort_errnum(result, "Mutex::lock(): pthread_mutex_lock failed");
+       if (result != 0) {
+               os::abort_errnum(result, "Mutex::lock(): pthread_mutex_lock failed");
+       }
 }
 
 
@@ -114,20 +138,20 @@ inline void Mutex::lock()
  */
 inline void Mutex::unlock()
 {
-       int result;
-
-       result = pthread_mutex_unlock(&_mutex);
+       int result = pthread_mutex_unlock(&_mutex);
 
-       if (result != 0)
-               vm_abort_errnum(result, "Mutex::unlock: pthread_mutex_unlock failed");
+       if (result != 0) {
+               os::abort_errnum(result, "Mutex::unlock: pthread_mutex_unlock failed");
+       }
 }
 
 #else
 
 // This structure must have the same layout as the class above.
-typedef struct Mutex {
-       pthread_mutex_t _mutex;
-} Mutex;
+struct Mutex {
+       pthread_mutex_t     _mutex;
+       pthread_mutexattr_t _attr;
+};
 
 Mutex* Mutex_new();
 void   Mutex_delete(Mutex* mutex);
index c896910d34d876b82c442089a50587689390cc7f..e109ca40c14a3b4a0d11be615ef1ef3a027f4995 100644 (file)
 # include "mm/cacao-gc/gc.h"
 #endif
 
-#include "native/jni.h"
 #include "native/llni.h"
-#include "native/native.h"
+#include "native/native.hpp"
 
 #include "threads/condition.hpp"
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
 #include "threads/mutex.hpp"
-#include "threads/threadlist.h"
+#include "threads/threadlist.hpp"
 #include "threads/thread.hpp"
 
 #include "toolbox/logging.h"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/exceptions.hpp"
 #include "vm/global.h"
 #include "vm/globals.hpp"
 #endif
 
 
-// FIXME For now we export everything as C functions.
-extern "C" {
-
 #if defined(__DARWIN__)
 /* Darwin has no working semaphore implementation.  This one is taken
    from Boehm-GC. */
@@ -433,33 +429,6 @@ void threads_startworld(void)
 #endif
 
 
-/* threads_impl_thread_init ****************************************************
-
-   Initialize OS-level locking constructs in threadobject.
-
-   IN:
-      t....the threadobject
-
-*******************************************************************************/
-
-void threads_impl_thread_init(threadobject *t)
-{
-       /* initialize the mutex and the condition */
-
-       t->flc_lock = new Mutex();
-       t->flc_cond = new Condition();
-
-       t->waitmutex = new Mutex();
-       t->waitcond = new Condition();
-
-       t->suspendmutex = new Mutex();
-       t->suspendcond = new Condition();
-
-#if defined(ENABLE_TLH)
-       tlh_init(&(t->tlh));
-#endif
-}
-
 /* threads_impl_thread_clear ***************************************************
 
    Clears all fields in threadobject the way an MZERO would have
@@ -510,7 +479,7 @@ void threads_impl_thread_clear(threadobject *t)
        t->es = NULL;
 #endif
 
-       MZERO(&t->dumpinfo, dumpinfo_t, 1);
+       // Simply reuse the existing dump memory.
 }
 
 /* threads_impl_thread_reuse ***************************************************
@@ -1323,7 +1292,7 @@ void threads_join_all_threads(void)
           compare against 1 because the current (main thread) is also a
           non-daemon thread. */
 
-       while (threadlist_get_non_daemons() > 1)
+       while (ThreadList::get_number_of_non_daemon_threads() > 1)
                cond_join->wait(mutex_join);
 
        /* leave join mutex */
@@ -1608,8 +1577,6 @@ void threads_tlh_remove_frame() {
 
 #endif
 
-} // extern "C"
-
 
 /*
  * These are local overrides for various environment variables in Emacs.
index e1e412ecb8402ac1eb945ea55d0ab61bb3250954..424ab84973ae45e08ee0b980b1cba389fbdf02d9 100644 (file)
 #ifndef _THREAD_POSIX_HPP
 #define _THREAD_POSIX_HPP
 
-/* forward typedefs ***********************************************************/
-
-typedef struct threadobject threadobject;
-
-
 #include "config.h"
 
 #include <pthread.h>
@@ -38,68 +33,17 @@ typedef struct threadobject threadobject;
 
 #include "vm/types.h"
 
-#include "mm/memory.h"
+
+// Includes required by Thread.
 
 #if defined(ENABLE_TLH)
-#include "mm/tlh.h"
+# include "mm/tlh.h"
 #endif
 
-#include "native/localref.h"
-
 #include "threads/condition.hpp"
 #include "threads/mutex.hpp"
 
-#include "threads/posix/lock.h"
-
 #include "vm/global.h"
-#include "vm/vm.hpp"
-
-#if defined(ENABLE_GC_CACAO)
-# include "vm/jit/executionstate.h"
-# include "vm/jit/replace.h"
-#endif
-
-#include "vm/jit/stacktrace.hpp"
-
-#if defined(ENABLE_INTRP)
-#include "vm/jit/intrp/intrp.h"
-#endif
-
-#if defined(__DARWIN__)
-# include <mach/mach.h>
-
-typedef struct {
-       Mutex* mutex;
-       Condition* cond;
-       int value;
-} sem_t;
-
-#else
-# include <semaphore.h>
-#endif
-
-
-// FIXME
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* current threadobject *******************************************************/
-
-#if defined(HAVE___THREAD)
-
-#define THREADOBJECT      thread_current
-
-extern __thread threadobject *thread_current;
-
-#else /* defined(HAVE___THREAD) */
-
-#define THREADOBJECT \
-       ((threadobject *) pthread_getspecific(thread_current_key))
-
-extern pthread_key_t thread_current_key;
-
-#endif /* defined(HAVE___THREAD) */
 
 
 /* threadobject ****************************************************************
@@ -117,6 +61,8 @@ extern pthread_key_t thread_current_key;
 #define SUSPEND_REASON_STOPWORLD 2      /* suspended from stop-thw-world      */
 
 
+typedef struct threadobject threadobject;
+
 struct threadobject {
        java_object_t        *object;       /* link to java.lang.Thread object    */
 
@@ -135,6 +81,7 @@ struct threadobject {
        /* for the sable tasuki lock extension */
        bool                  flc_bit;
        struct threadobject  *flc_list;     /* FLC list head for this thread      */
+       struct threadobject  *flc_tail;     /* tail pointer for FLC list          */
        struct threadobject  *flc_next;     /* next pointer for FLC list          */
        java_handle_t        *flc_object;
        Mutex*                flc_lock;     /* controlling access to these fields */
@@ -156,8 +103,8 @@ struct threadobject {
        u1                   *pc;           /* current PC (used for profiling)    */
 
        java_object_t        *_exceptionptr;     /* current exception             */
-       stackframeinfo_t     *_stackframeinfo;   /* current native stackframeinfo */
-       localref_table       *_localref_table;   /* JNI local references          */
+       struct stackframeinfo_t     *_stackframeinfo;   /* current native stackframeinfo */
+       struct localref_table       *_localref_table;   /* JNI local references          */
 
 #if defined(ENABLE_INTRP)
        Cell                 *_global_sp;        /* stack pointer for interpreter */
@@ -170,7 +117,7 @@ struct threadobject {
        executionstate_t     *es;
 #endif
 
-       dumpinfo_t            dumpinfo;     /* dump memory info structure         */
+       struct DumpMemory*    _dumpmemory;     ///< Dump memory structure.
 
 #if defined(ENABLE_DEBUG_FILTER)
        u2                    filterverbosecallctr[2]; /* counters for verbose call filter */
@@ -188,12 +135,27 @@ struct threadobject {
 #if defined(ENABLE_ESCAPE_REASON)
        void *escape_reasons;
 #endif
-
-       listnode_t            linkage;      /* threads-list                       */
-       listnode_t            linkage_free; /* free-list                          */
 };
 
 
+/* current threadobject *******************************************************/
+
+#if defined(HAVE___THREAD)
+
+#define THREADOBJECT      thread_current
+
+extern __thread threadobject *thread_current;
+
+#else /* defined(HAVE___THREAD) */
+
+#define THREADOBJECT \
+       ((threadobject *) pthread_getspecific(thread_current_key))
+
+extern pthread_key_t thread_current_key;
+
+#endif /* defined(HAVE___THREAD) */
+
+
 /* native-world flags *********************************************************/
 
 #if defined(ENABLE_GC_CACAO)
@@ -219,18 +181,62 @@ struct threadobject {
 #endif
 
 
-/* inline functions ***********************************************************/
+// FIXME
+#ifdef __cplusplus
+extern "C" {
+#endif
+inline static threadobject* thread_get_current(void);
+#ifdef __cplusplus
+}
+#endif
+
 
-/* thread_get_current **********************************************************
+// Includes.
+#include "mm/memory.h"
 
-   Return the threadobject of the current thread.
-   
-   RETURN:
-       the current threadobject *
+#include "native/localref.hpp"
 
-*******************************************************************************/
+#include "threads/lock.hpp"
+
+#include "vm/global.h"
+#include "vm/vm.hpp"
+
+#if defined(ENABLE_GC_CACAO)
+# include "vm/jit/executionstate.h"
+# include "vm/jit/replace.hpp"
+#endif
 
-inline static threadobject *thread_get_current(void)
+#if defined(ENABLE_INTRP)
+#include "vm/jit/intrp/intrp.h"
+#endif
+
+#if defined(__DARWIN__)
+# include <mach/mach.h>
+
+typedef struct {
+       Mutex* mutex;
+       Condition* cond;
+       int value;
+} sem_t;
+
+#else
+# include <semaphore.h>
+#endif
+
+
+// FIXME
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* inline functions ***********************************************************/
+
+/**
+ * Return the Thread object of the current thread.
+ *
+ * @return The current Thread object.
+ */
+inline static threadobject* thread_get_current(void)
 {
        threadobject *t;
 
@@ -244,16 +250,12 @@ inline static threadobject *thread_get_current(void)
 }
 
 
-/* thread_set_current **********************************************************
-
-   Set the current thread object.
-   
-   IN:
-      t ... the thread object to set
-
-*******************************************************************************/
-
-inline static void thread_set_current(threadobject *t)
+/**
+ * Set the current Thread object.
+ *
+ * @param t The thread object to set.
+ */
+inline static void thread_set_current(threadobject* t)
 {
 #if defined(HAVE___THREAD)
        thread_current = t;
@@ -268,12 +270,12 @@ inline static void thread_set_current(threadobject *t)
 }
 
 
-inline static stackframeinfo_t *threads_get_current_stackframeinfo(void)
+inline static struct stackframeinfo_t* threads_get_current_stackframeinfo(void)
 {
        return THREADOBJECT->_stackframeinfo;
 }
 
-inline static void threads_set_current_stackframeinfo(stackframeinfo_t *sfi)
+inline static void threads_set_current_stackframeinfo(struct stackframeinfo_t* sfi)
 {
        THREADOBJECT->_stackframeinfo = sfi;
 }
index 4d4d4c6440d25fe49eed0429647927590400753f..b688616dacc191272e8198c6b06114de0f724fb2 100644 (file)
 # include "mm/boehm-gc/include/gc.h"
 #endif
 
-#include "native/jni.h"
 #include "native/llni.h"
-#include "native/native.h"
+#include "native/native.hpp"
 
-#include "threads/lock-common.h"
-#include "threads/threadlist.h"
+#include "threads/lock.hpp"
+#include "threads/threadlist.hpp"
 #include "threads/thread.hpp"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/class.h"
 #include "vm/exceptions.hpp"
 #include "vm/globals.hpp"
@@ -65,9 +64,6 @@
 #include "vm/jit/stacktrace.hpp"
 
 
-// FIXME
-extern "C" {
-
 /* global variables ***********************************************************/
 
 static methodinfo    *thread_method_init;
@@ -409,7 +405,7 @@ static void thread_create_initial_thread(void)
        /* Get the main-thread (NOTE: The main thread is always the first
           thread in the list). */
 
-       t = threadlist_first();
+       t = ThreadList::get_main_thread();
 
        /* The thread name. */
 
@@ -451,21 +447,17 @@ static threadobject *thread_new(void)
        
        /* Lock the thread lists */
 
-       threadlist_lock();
+       ThreadList::lock();
 
-       index = threadlist_get_free_index();
+       index = ThreadList::get_free_thread_index();
 
        /* Allocate a thread data structure. */
 
        /* First, try to get one from the free-list. */
 
-       t = threadlist_free_first();
+       t = ThreadList::get_free_thread();
 
        if (t != NULL) {
-               /* Remove from free list. */
-
-               threadlist_free_remove(t);
-
                /* Equivalent of MZERO on the else path */
 
                threads_impl_thread_clear(t);
@@ -486,6 +478,20 @@ static threadobject *thread_new(void)
 
                MZERO(t, threadobject, 1);
 
+               // Initialize the mutex and the condition.
+               t->flc_lock = new Mutex();
+               t->flc_cond = new Condition();
+
+               t->waitmutex = new Mutex();
+               t->waitcond = new Condition();
+
+               t->suspendmutex = new Mutex();
+               t->suspendcond = new Condition();
+
+#if defined(ENABLE_TLH)
+               tlh_init(&(t->tlh));
+#endif
+
 #if defined(ENABLE_GC_CACAO)
                /* Register reference to java.lang.Thread with the GC. */
                /* FIXME is it ok to do this only once? */
@@ -494,9 +500,7 @@ static threadobject *thread_new(void)
                gc_reference_register(&(t->_exceptionptr), GC_REFTYPE_THREADOBJECT);
 #endif
 
-               /* Initialize the implementation-specific bits. */
-
-               threads_impl_thread_init(t);
+               t->_dumpmemory = new DumpMemory();
        }
 
        /* Pre-compute the thinlock-word. */
@@ -504,7 +508,7 @@ static threadobject *thread_new(void)
        assert(index != 0);
 
        t->index     = index;
-       t->thinlock  = lock_pre_compute_thinlock(t->index);
+       t->thinlock  = Lockword::pre_compute_thinlock(t->index);
        t->flags     = 0;
        t->state     = THREAD_STATE_NEW;
 
@@ -518,11 +522,11 @@ static threadobject *thread_new(void)
 
        /* Add the thread to the thread list. */
 
-       threadlist_add(t);
+       ThreadList::add_to_active_thread_list(t);
 
        /* Unlock the thread lists. */
 
-       threadlist_unlock();
+       ThreadList::unlock();
 
        return t;
 }
@@ -541,29 +545,13 @@ static threadobject *thread_new(void)
 
 void thread_free(threadobject *t)
 {
-       /* Lock the thread lists. */
-
-       threadlist_lock();
-
-       /* Remove the thread from the thread-list. */
-
-       threadlist_remove(t);
-
-       /* Add the thread index to the free list. */
-
-       threadlist_index_add(t->index);
-
        /* Set the reference to the Java object to NULL. */
 
        thread_set_object(t, NULL);
 
-       /* Add the thread data structure to the free list. */
-
-       threadlist_free_add(t);
-
-       /* Unlock the thread lists. */
+       /* Release the thread. */
 
-       threadlist_unlock();
+       ThreadList::release_thread(t);
 }
 
 
@@ -887,7 +875,7 @@ void thread_fprint_name(threadobject *t, FILE *stream)
 #elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) || defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
 
        /* FIXME: In OpenJDK and CLDC the name is a char[]. */
-       java_chararray_t *name;
+       //java_chararray_t *name;
 
        /* FIXME This prints to stdout. */
        utf_display_printable_ascii(utf_null);
@@ -1006,7 +994,7 @@ void thread_set_state_runnable(threadobject *t)
 {
        /* Set the state inside a lock. */
 
-       threadlist_lock();
+       ThreadList::lock();
 
        if (t->state != THREAD_STATE_TERMINATED) {
                t->state = THREAD_STATE_RUNNABLE;
@@ -1014,7 +1002,7 @@ void thread_set_state_runnable(threadobject *t)
                DEBUGTHREADS("is RUNNABLE", t);
        }
 
-       threadlist_unlock();
+       ThreadList::unlock();
 }
 
 
@@ -1031,7 +1019,7 @@ void thread_set_state_waiting(threadobject *t)
 {
        /* Set the state inside a lock. */
 
-       threadlist_lock();
+       ThreadList::lock();
 
        if (t->state != THREAD_STATE_TERMINATED) {
                t->state = THREAD_STATE_WAITING;
@@ -1039,7 +1027,7 @@ void thread_set_state_waiting(threadobject *t)
                DEBUGTHREADS("is WAITING", t);
        }
 
-       threadlist_unlock();
+       ThreadList::unlock();
 }
 
 
@@ -1057,7 +1045,7 @@ void thread_set_state_timed_waiting(threadobject *t)
 {
        /* Set the state inside a lock. */
 
-       threadlist_lock();
+       ThreadList::lock();
 
        if (t->state != THREAD_STATE_TERMINATED) {
                t->state = THREAD_STATE_TIMED_WAITING;
@@ -1065,7 +1053,7 @@ void thread_set_state_timed_waiting(threadobject *t)
                DEBUGTHREADS("is TIMED_WAITING", t);
        }
 
-       threadlist_unlock();
+       ThreadList::unlock();
 }
 
 
@@ -1080,13 +1068,13 @@ void thread_set_state_terminated(threadobject *t)
 {
        /* Set the state inside a lock. */
 
-       threadlist_lock();
+       ThreadList::lock();
 
        t->state = THREAD_STATE_TERMINATED;
 
        DEBUGTHREADS("is TERMINATED", t);
 
-       threadlist_unlock();
+       ThreadList::unlock();
 }
 
 
@@ -1112,23 +1100,11 @@ threadobject *thread_get_thread(java_handle_t *h)
 #elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
 
        /* XXX This is just a quick hack. */
-       threadobject* t;
-       bool          equal;
-
-       threadlist_lock();
-
-       for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
-               LLNI_equals(t->object, h, equal);
-
-               if (equal == true)
-                       break;
-       }
-
-       threadlist_unlock();
+       threadobject* t = ThreadList::get_thread_from_java_object(h);
 
 #elif defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
 
-       log_println("threads_get_thread: IMPLEMENT ME!");
+       log_println("thread_get_thread: IMPLEMENT ME!");
        threadobject* t = NULL;
 
 #else
@@ -1172,66 +1148,6 @@ bool threads_thread_is_alive(threadobject *t)
 }
 
 
-/* threads_dump ****************************************************************
-
-   Dumps info for all threads running in the JVM.  This function is
-   called when SIGQUIT (<ctrl>-\) is sent to CACAO.
-
-*******************************************************************************/
-
-void threads_dump(void)
-{
-       threadobject *t;
-
-       /* XXX we should stop the world here */
-
-       /* Lock the thread lists. */
-
-       threadlist_lock();
-
-       printf("Full thread dump CACAO "VERSION":\n");
-
-       /* iterate over all started threads */
-
-       for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
-               /* ignore threads which are in state NEW */
-               if (t->state == THREAD_STATE_NEW)
-                       continue;
-
-#if defined(ENABLE_GC_CACAO)
-               /* Suspend the thread. */
-               /* XXX Is the suspend reason correct? */
-
-               if (threads_suspend_thread(t, SUSPEND_REASON_JNI) == false)
-                       vm_abort("threads_dump: threads_suspend_thread failed");
-#endif
-
-               /* Print thread info. */
-
-               printf("\n");
-               thread_print_info(t);
-               printf("\n");
-
-               /* Print trace of thread. */
-
-               stacktrace_print_of_thread(t);
-
-#if defined(ENABLE_GC_CACAO)
-               /* Resume the thread. */
-
-               if (threads_resume_thread(t) == false)
-                       vm_abort("threads_dump: threads_resume_thread failed");
-#endif
-       }
-
-       /* Unlock the thread lists. */
-
-       threadlist_unlock();
-}
-
-} // extern "C"
-
-
 /*
  * These are local overrides for various environment variables in Emacs.
  * Please do not remove this and leave it at the end of the file, where
index c6336c80afd59dcbdce6334b5adfb8c05529b545..b50db4370728cc6ae88aae68d9d921a6781c9d97 100644 (file)
 
 #include "config.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #include "vm/types.h"
 
 // Include early to get threadobject.
@@ -43,7 +39,6 @@ extern "C" {
 
 #include "vm/os.hpp"
 
-#include "native/jni.h"
 #include "native/llni.h"
 
 #include "threads/mutex.hpp"
@@ -97,6 +92,10 @@ extern bool threads_pthreads_implementation_nptl;
 #endif
 
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /* inline functions ***********************************************************/
 
 /* thread_get_object ***********************************************************
@@ -333,8 +332,6 @@ threadobject *thread_get_thread(java_handle_t *h);
 
 bool          threads_thread_is_alive(threadobject *t);
 
-void          threads_dump(void);
-
 
 /* implementation specific functions */
 
@@ -349,7 +346,6 @@ void          threads_mutex_gc_unlock(void);
 void          threads_mutex_join_lock(void);
 void          threads_mutex_join_unlock(void);
 
-void          threads_impl_thread_init(threadobject *t);
 void          threads_impl_thread_clear(threadobject *t);
 void          threads_impl_thread_reuse(threadobject *t);
 void          threads_impl_thread_free(threadobject *t);
@@ -357,12 +353,12 @@ void          threads_impl_thread_start(threadobject *thread, functionptr f);
 
 void          threads_yield(void);
 
-#endif /* ENABLE_THREADS */
-
 #ifdef __cplusplus
 }
 #endif
 
+#endif /* ENABLE_THREADS */
+
 #endif // _THREAD_HPP
 
 
diff --git a/src/threads/threadlist.c b/src/threads/threadlist.c
deleted file mode 100644 (file)
index b585f22..0000000
+++ /dev/null
@@ -1,379 +0,0 @@
-/* src/threads/threadlist.c - different thread-lists
-
-   Copyright (C) 2008
-   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
-
-   This file is part of CACAO.
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2, or (at
-   your option) any later version.
-
-   This program is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-   02110-1301, USA.
-
-*/
-
-
-#include "config.h"
-
-#include <stdint.h>
-
-#include "mm/memory.h"
-
-#include "threads/mutex.hpp"
-#include "threads/threadlist.h"
-#include "threads/thread.hpp"
-
-#include "toolbox/list.h"
-
-#include "vm/options.h"
-
-
-/* global variables ***********************************************************/
-
-static Mutex* threadlist_mutex;           /* global mutex for the thread list */
-
-static list_t *list_thread;                            /* global threads list */
-static list_t *list_thread_free;                  /* global free threads list */
-static list_t *list_thread_index_free;
-
-
-typedef struct thread_index_t {
-       int32_t    index;
-       listnode_t linkage;
-} thread_index_t;
-
-
-/* threadlist_init *************************************************************
-
-   Initialize thread-lists.
-
-*******************************************************************************/
-
-void threadlist_init(void)
-{
-       TRACESUBSYSTEMINITIALIZATION("threadlist_init");
-
-       /* Initialize the thread list mutex. */
-
-       threadlist_mutex = Mutex_new();
-
-       /* Initialize the thread lists. */
-
-       list_thread            = list_create(OFFSET(threadobject, linkage));
-       list_thread_free       = list_create(OFFSET(threadobject, linkage_free));
-       list_thread_index_free = list_create(OFFSET(thread_index_t, linkage));
-}
-
-
-/* threadlist_lock *************************************************************
-
-   Enter the thread list mutex.
-
-   NOTE: We need this function as we can't use an internal lock for
-         the threads lists because the thread's lock is initialized in
-         threads_table_add (when we have the thread index), but we
-         already need the lock at the entry of the function.
-
-*******************************************************************************/
-
-void threadlist_lock(void)
-{
-       Mutex_lock(threadlist_mutex);
-}
-
-
-/* threadlist_unlock *********************************************************
-
-   Leave the thread list mutex.
-
-*******************************************************************************/
-
-void threadlist_unlock(void)
-{
-       Mutex_unlock(threadlist_mutex);
-}
-
-
-/* threadlist_add **************************************************************
-
-   Add the given threadobject as last entry to the thread list.
-
-   IN:
-       t ... threadobject to be added
-
-*******************************************************************************/
-
-void threadlist_add(threadobject *t)
-{
-       list_add_last(list_thread, t);
-}
-
-
-/* threadlist_remove ***********************************************************
-
-   Remove the given threadobject from the thread list.
-
-   IN:
-       t ... threadobject to be removed
-
-*******************************************************************************/
-
-void threadlist_remove(threadobject *t)
-{
-       list_remove(list_thread, t);
-}
-
-
-/* threadlist_first ************************************************************
-
-   Return the first entry in the thread list.
-
-   RETURN:
-       threadobject of the first entry
-
-*******************************************************************************/
-
-threadobject *threadlist_first(void)
-{
-       threadobject *t;
-
-       t = list_first(list_thread);
-
-       return t;
-}
-
-
-/* threadlist_next *************************************************************
-
-   Return the next entry in the thread list.
-
-   IN:
-       t ... threadobject to get next thread of
-
-   RETURN:
-       threadobject of the next entry
-
-*******************************************************************************/
-
-threadobject *threadlist_next(threadobject *t)
-{
-       threadobject *next;
-
-       next = list_next(list_thread, t);
-
-       return next;
-}
-
-
-/* threadlist_free_add *********************************************************
-
-   Add the given threadobject as last entry to the free thread list.
-
-   IN:
-       t ... threadobject to be added
-
-*******************************************************************************/
-
-void threadlist_free_add(threadobject *t)
-{
-       list_add_last(list_thread_free, t);
-}
-
-
-/* threadlist_free_remove ******************************************************
-
-   Remove the given entry from the free thread list.
-
-   IN:
-       t ... threadobject to be removed
-
-*******************************************************************************/
-
-void threadlist_free_remove(threadobject *t)
-{
-       list_remove(list_thread_free, t);
-}
-
-
-/* threadlist_free_first *******************************************************
-
-   Return the first entry in the free thread list.
-
-   RETURN:
-       threadobject of the first free entry
-
-*******************************************************************************/
-
-threadobject *threadlist_free_first(void)
-{
-       threadobject *t;
-
-       t = list_first(list_thread_free);
-
-       return t;
-}
-
-
-/* threadlist_get_non_daemons **************************************************
-
-   Return the number of non-daemon threads.
-
-   NOTE: This function does a linear-search over the threads list,
-         because it's only used for joining the threads.
-
-*******************************************************************************/
-
-int threadlist_get_non_daemons(void)
-{
-       threadobject *t;
-       int           nondaemons;
-
-       /* Lock the thread lists. */
-
-       threadlist_lock();
-
-       nondaemons = 0;
-
-       for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
-               if (!thread_is_daemon(t))
-                       nondaemons++;
-       }
-
-       /* Unlock the thread lists. */
-
-       threadlist_unlock();
-
-       return nondaemons;
-}
-
-
-/* threadlist_index_first ******************************************************
-
-   Return the first entry in the thread-index list.
-
-   RETURN VALUE:
-       thread-index structure
-
-*******************************************************************************/
-
-static inline thread_index_t *threadlist_index_first(void)
-{
-       thread_index_t *ti;
-
-       ti = list_first(list_thread_index_free);
-
-       return ti;
-}
-
-
-/* threadlist_index_add ********************************************************
-
-   Add the given thread-index to the thread-index free list.
-
-   IN:
-       i ... thread index
-
-*******************************************************************************/
-
-void threadlist_index_add(int index)
-{
-       thread_index_t *ti;
-
-       ti = NEW(thread_index_t);
-
-#if defined(ENABLE_STATISTICS)
-       if (opt_stat)
-               size_thread_index_t += sizeof(thread_index_t);
-#endif
-
-       /* Set the index in the structure. */
-
-       ti->index = index;
-
-       list_add_last(list_thread_index_free, ti);
-}
-
-
-/* threadlist_index_remove *****************************************************
-
-   Remove the given thread-index from the thread-index list and free
-   the thread-index structure.
-
-   IN:
-       ti ... thread-index structure
-
-*******************************************************************************/
-
-static inline void threadlist_index_remove(thread_index_t *ti)
-{
-       list_remove(list_thread_index_free, ti);
-
-       FREE(ti, thread_index_t);
-
-#if defined(ENABLE_STATISTICS)
-       if (opt_stat)
-               size_thread_index_t -= sizeof(thread_index_t);
-#endif
-}
-
-
-/* threadlist_get_free_index ***************************************************
-
-   Return a free thread index.
-
-   RETURN VALUE:
-       free thread index
-
-*******************************************************************************/
-
-int threadlist_get_free_index(void)
-{
-       thread_index_t *ti;
-       int             index;
-
-       /* Try to get a thread index from the free-list. */
-
-       ti = threadlist_index_first();
-
-       /* Is a free thread index available? */
-
-       if (ti != NULL) {
-               /* Yes, get the index and remove it from the free list. */
-
-               index = ti->index;
-
-               threadlist_index_remove(ti);
-       }
-       else {
-               /* Get a new the thread index. */
-
-               index = list_thread->size + 1;
-       }
-
-       return index;
-}
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
diff --git a/src/threads/threadlist.cpp b/src/threads/threadlist.cpp
new file mode 100644 (file)
index 0000000..bcf7f0e
--- /dev/null
@@ -0,0 +1,284 @@
+/* src/threads/threadlist.cpp - thread list
+
+   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 <algorithm>
+
+#include "threads/mutex.hpp"
+#include "threads/threadlist.hpp"
+#include "threads/thread.hpp"
+
+#include "toolbox/list.hpp"
+#include "toolbox/logging.h"
+
+#include "vm/jit/stacktrace.hpp"
+
+
+/* class variables */
+
+Mutex               ThreadList::_mutex;                // a mutex for all thread lists
+
+list<threadobject*> ThreadList::_active_thread_list;   // list of active threads
+list<threadobject*> ThreadList::_free_thread_list;     // list of free threads
+list<int32_t>       ThreadList::_free_index_list;      // list of free thread indexes
+
+int32_t             ThreadList::_number_of_non_daemon_threads;
+
+
+/**
+ * Dumps info for all threads running in the VM.  This function is
+ * called when SIGQUIT (<ctrl>-\) is sent to the VM.
+ */
+void ThreadList::dump_threads()
+{
+       // XXX we should stop the world here
+       // Lock the thread lists.
+       lock();
+
+       printf("Full thread dump CACAO "VERSION":\n");
+
+       // Iterate over all started threads.
+       for (List<threadobject*>::iterator it = _active_thread_list.begin(); it != _active_thread_list.end(); it++) {
+               threadobject* t = *it;
+
+               // Ignore threads which are in state NEW.
+               if (t->state == THREAD_STATE_NEW)
+                       continue;
+
+#if defined(ENABLE_GC_CACAO)
+               /* Suspend the thread. */
+               /* XXX Is the suspend reason correct? */
+
+               if (threads_suspend_thread(t, SUSPEND_REASON_JNI) == false)
+                       vm_abort("threads_dump: threads_suspend_thread failed");
+#endif
+
+               /* Print thread info. */
+
+               printf("\n");
+               thread_print_info(t);
+               printf("\n");
+
+               /* Print trace of thread. */
+
+               stacktrace_print_of_thread(t);
+
+#if defined(ENABLE_GC_CACAO)
+               /* Resume the thread. */
+
+               if (threads_resume_thread(t) == false)
+                       vm_abort("threads_dump: threads_resume_thread failed");
+#endif
+       }
+
+       // Unlock the thread lists.
+       unlock();
+}
+
+
+/**
+ * Return a free thread object.
+ *
+ * @return free thread object or NULL if none available
+ */
+threadobject* ThreadList::get_free_thread()
+{
+       threadobject* t = NULL;
+
+       // Do we have free threads in the free-list?
+       if (_free_thread_list.empty() == false) {
+               // Yes, get the index and remove it from the free list.
+               threadobject* t = _free_thread_list.front();
+               _free_thread_list.remove(t);
+       }
+
+       return t;
+}
+
+
+/**
+ * Return a free thread index.
+ *
+ * @return free thread index
+ */
+int32_t ThreadList::get_free_thread_index()
+{
+       int32_t index;
+
+       // Do we have free indexes in the free-list?
+       if (_free_index_list.empty() == false) {
+               // Yes, get the index and remove it from the free list.
+               index = _free_index_list.front();
+               _free_index_list.remove(index);
+       }
+       else {
+               // Get a new the thread index.
+               index = _active_thread_list.size() + 1;
+       }
+
+       return index;
+}
+
+
+/**
+ * Return the number of non-daemon threads.
+ *
+ * NOTE: This function does a linear-search over the threads list,
+ *       because it is only used for joining the threads.
+ *
+ * @return number of non daemon threads
+ */
+int32_t ThreadList::get_number_of_non_daemon_threads(void)
+{
+       int nondaemons = 0;
+
+       lock();
+
+       for (List<threadobject*>::iterator it = _active_thread_list.begin(); it != _active_thread_list.end(); it++) {
+               threadobject* t = *it;
+
+               if (!thread_is_daemon(t))
+                       nondaemons++;
+       }
+
+       unlock();
+
+       return nondaemons;
+}
+
+
+/**
+ * Return the thread object with the given index.
+ *
+ * @return thread object
+ */
+threadobject* ThreadList::get_thread_by_index(int32_t index)
+{
+       lock();
+
+       List<threadobject*>::iterator it = find_if(_active_thread_list.begin(), _active_thread_list.end(), std::bind2nd(comparator(), index));
+
+       // No thread found.
+       if (it == _active_thread_list.end()) {
+               unlock();
+               return NULL;
+       }
+
+       threadobject* t = *it;
+
+       // The thread found is in state new.
+       if (t->state == THREAD_STATE_NEW) {
+               unlock();
+               return NULL;
+       }
+
+       unlock();
+       return t;
+}
+
+
+/**
+ * Return the Java thread object from the given thread object.
+ *
+ * @return Java thread object
+ */
+threadobject* ThreadList::get_thread_from_java_object(java_handle_t* h)
+{
+       List<threadobject*>::iterator it;
+       threadobject* t;
+       bool          equal;
+
+       lock();
+
+       for (it = _active_thread_list.begin(); it != _active_thread_list.end(); it++) {
+               t = *it;
+
+               LLNI_equals(t->object, h, equal);
+
+               if (equal == true) {
+                       unlock();
+                       return t;
+               }
+       }
+
+       unlock();
+
+       return NULL;
+}
+
+
+/**
+ * Release the thread.
+ *
+ * @return free thread index
+ */
+void ThreadList::release_thread(threadobject* t)
+{
+       lock();
+
+       // Move thread from active thread list to free thread list.
+       remove_from_active_thread_list(t);
+       add_to_free_thread_list(t);
+
+       // Add thread index to free index list.
+       add_to_free_index_list(t->index);
+
+       unlock();
+}
+
+
+/* C interface functions ******************************************************/
+
+extern "C" {
+       void ThreadList_lock() { ThreadList::lock(); }
+       void ThreadList_unlock() { ThreadList::unlock(); }
+       void ThreadList_dump_threads() { ThreadList::dump_threads(); }
+       void ThreadList_release_thread(threadobject* t) { ThreadList::release_thread(t); }
+       threadobject* ThreadList_get_free_thread() { return ThreadList::get_free_thread(); }
+       int32_t ThreadList_get_free_thread_index() { return ThreadList::get_free_thread_index(); }
+       void ThreadList_add_to_active_thread_list(threadobject* t) { ThreadList::add_to_active_thread_list(t); }
+       threadobject* ThreadList_get_thread_by_index(int32_t index) { return ThreadList::get_thread_by_index(index); }
+       threadobject* ThreadList_get_main_thread() { return ThreadList::get_main_thread(); }
+       threadobject* ThreadList_get_thread_from_java_object(java_handle_t* h) { return ThreadList::get_thread_from_java_object(h); }
+
+       int32_t ThreadList_get_number_of_non_daemon_threads() { return ThreadList::get_number_of_non_daemon_threads(); }
+}
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
diff --git a/src/threads/threadlist.h b/src/threads/threadlist.h
deleted file mode 100644 (file)
index 6f2ae0a..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-/* src/threads/threadlist.h - different thread-lists
-
-   Copyright (C) 2008
-   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
-
-   This file is part of CACAO.
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2, or (at
-   your option) any later version.
-
-   This program is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-   02110-1301, USA.
-
-*/
-
-
-#ifndef _THREADLIST_H
-#define _THREADLIST_H
-
-#include "config.h"
-
-#include <stdint.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "threads/thread.hpp"
-
-
-/* function prototypes ********************************************************/
-
-void          threadlist_init(void);
-
-void          threadlist_add(threadobject *t);
-void          threadlist_remove(threadobject *t);
-threadobject *threadlist_first(void);
-threadobject *threadlist_next(threadobject *t);
-
-void          threadlist_free_add(threadobject *t);
-void          threadlist_free_remove(threadobject *t);
-threadobject *threadlist_free_first(void);
-
-int           threadlist_get_non_daemons(void);
-
-void          threadlist_index_add(int index);
-int           threadlist_get_free_index(void);
-
-/* implementation specific functions */
-
-void          threadlist_impl_init(void);
-
-void          threadlist_lock(void);
-void          threadlist_unlock(void);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _THREADLIST_H */
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
diff --git a/src/threads/threadlist.hpp b/src/threads/threadlist.hpp
new file mode 100644 (file)
index 0000000..2a9f205
--- /dev/null
@@ -0,0 +1,144 @@
+/* src/threads/threadlist.hpp - different thread-lists
+
+   Copyright (C) 2008
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+   This file is part of CACAO.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+*/
+
+
+#ifndef _THREADLIST_HPP
+#define _THREADLIST_HPP
+
+#include "config.h"
+
+#include <stdint.h>
+
+#include "threads/thread.hpp"
+
+#include "toolbox/list.hpp"
+
+
+/* ThreadList *****************************************************************/
+
+#ifdef __cplusplus
+
+using std::list;
+
+class ThreadList {
+private:
+       static Mutex               _mutex;              // a mutex for all thread lists
+
+       static list<threadobject*> _active_thread_list; // list of active threads
+       static list<threadobject*> _free_thread_list;   // list of free threads
+       static list<int32_t>       _free_index_list;    // list of free thread indexes
+
+       static int32_t             _number_of_non_daemon_threads;
+
+       static inline void          remove_from_active_thread_list(threadobject* t);
+       static inline void          add_to_free_thread_list(threadobject* t);
+       static inline void          add_to_free_index_list(int32_t index);
+
+private:
+       // Comparator class.
+       class comparator : public std::binary_function<threadobject*, int32_t, bool> {
+       public:
+               bool operator() (const threadobject* t, const int32_t index) const
+               {
+                       return (t->index == index);
+               }
+       };
+
+public:
+       static inline void          lock()   { _mutex.lock(); }
+       static inline void          unlock() { _mutex.unlock(); }
+
+       // TODO make private
+       static inline void          add_to_active_thread_list(threadobject* t);
+
+       static void                 dump_threads();
+       static inline threadobject* get_main_thread();
+       static threadobject*        get_free_thread();
+       static int32_t              get_free_thread_index();
+       static int32_t              get_number_of_non_daemon_threads();
+       static threadobject*        get_thread_by_index(int32_t index);
+       static threadobject*        get_thread_from_java_object(java_handle_t* h);
+       static void                 release_thread(threadobject* t);
+};
+
+
+inline void ThreadList::add_to_active_thread_list(threadobject* t)
+{
+       _active_thread_list.push_back(t);
+}
+
+inline void ThreadList::remove_from_active_thread_list(threadobject* t)
+{
+       _active_thread_list.remove(t);
+}
+
+inline void ThreadList::add_to_free_thread_list(threadobject* t)
+{
+       _free_thread_list.push_back(t);
+}
+
+inline void ThreadList::add_to_free_index_list(int32_t index)
+{
+       _free_index_list.push_back(index);
+}
+
+inline threadobject* ThreadList::get_main_thread()
+{
+       return _active_thread_list.front();
+}
+
+#else
+
+typedef struct ThreadList ThreadList;
+
+void ThreadList_lock();
+void ThreadList_unlock();
+void ThreadList_dump_threads();
+void ThreadList_release_thread(threadobject* t);
+threadobject* ThreadList_get_free_thread();
+int32_t ThreadList_get_free_thread_index();
+void ThreadList_add_to_active_thread_list(threadobject* t);
+threadobject* ThreadList_get_thread_by_index(int32_t index);
+threadobject* ThreadList_get_main_thread();
+threadobject* ThreadList_get_thread_from_java_object(java_handle_t* h);
+int32_t ThreadList_get_number_of_non_daemon_threads();
+
+#endif
+
+#endif // _THREADLIST_HPP
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
index e6d1085cd40a0158c499e11e25802783ae87ce1b..c5c2cae128d049c22d2c0a37dde36f5f7a120854 100644 (file)
@@ -1,9 +1,7 @@
 ## src/toolbox/Makefile.am
 ##
-## Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
-## C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
-## E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
-## J. Wenninger, Institut f. Computersprachen - TU Wien
+## Copyright (C) 1996-2005, 2006, 2007, 2008
+## CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 ##
 ## This file is part of CACAO.
 ##
 ## along with this program; if not, write to the Free Software
 ## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 ## 02110-1301, USA.
-##
-## Contact: cacao@cacaojvm.org
-##
-## Authors: Christian Thalinger
-##
-##
+
+
 AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/src/vm/jit/$(ARCH_DIR) -I$(top_srcdir)/src/vm/jit/$(ARCH_DIR)/$(OS_DIR)
 
 LIBS =
@@ -39,18 +33,13 @@ libtoolbox_la_SOURCES = \
        avl.h \
        bitvector.c \
        bitvector.h \
-       chain.c \
-       chain.h \
        hashtable.c \
        hashtable.h \
-       list.c \
-       list.h \
+       list.hpp \
        logging.c \
        logging.h \
        set.h \
        set.c \
-       tree.c \
-       tree.h \
        util.c \
        util.h \
        worklist.c \
index c968fa8a9e9d020800465b2044d998539f4beed4..c95513b30ea0312a43e77701b4452ab9046be80f 100644 (file)
@@ -73,6 +73,10 @@ struct avl_node_t {
 
 /* function prototypes ********************************************************/
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 avl_tree_t *avl_create(avl_comparator *comparator);
 bool        avl_insert(avl_tree_t *tree, void *data);
 void       *avl_find(avl_tree_t *tree, void *data);
@@ -81,6 +85,10 @@ void       *avl_find(avl_tree_t *tree, void *data);
 void        avl_dump(avl_node_t* node, s4 indent);
 #endif
 
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
 #endif /* _AVL_H */
 
 
index bde41ff7ce95d2f4aecff7f569eede28e8d8ede1..66b9df11561033c0222f2486dd8a1f527b5551a0 100644 (file)
@@ -1,9 +1,8 @@
 /* src/toolbox/bitvector.c - bitvector implementation
 
-   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
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+   Copyright (C) 2008 Theobroma Systems Ltd.
 
    This file is part of CACAO.
 
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
    02111-1307, USA.
 
-   Contact: cacao@complang.tuwien.ac.at
-
-   Authors: Christian Ullrich
+*/
 
 
-*/
+#include "config.h"
 
 #include "mm/memory.h"
 #include "toolbox/bitvector.h"
@@ -115,7 +112,7 @@ bitvector bv_new(int size) {
     /* n = (((size+7)/8) + sizeof(int) - 1)/sizeof(int);  */
        n = BV_NUM_INTS(size);
 
-       bv = DMNEW(int, n);
+       bv = DumpMemory_allocate(sizeof(int) * n);
 
        for(i = 0; i < n; i++) bv[i] = 0;
    
diff --git a/src/toolbox/chain.c b/src/toolbox/chain.c
deleted file mode 100644 (file)
index ae1bb7c..0000000
+++ /dev/null
@@ -1,315 +0,0 @@
-/* src/toolbox/chain.c - management of doubly linked lists with external linking
-
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
-   C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
-   E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
-   J. Wenninger, Institut f. Computersprachen - TU Wien
-
-   This file is part of CACAO.
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2, or (at
-   your option) any later version.
-
-   This program is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-   02110-1301, USA.
-
-   Contact: cacao@cacaojvm.org
-
-   Authors: Reinhard Grafl
-
-   Changes: Christian Thalinger
-
-*/
-
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-
-#include "mm/memory.h"
-#include "toolbox/chain.h"
-
-
-chain *chain_new(void)
-{
-       chain *c;
-       
-       c = NEW(chain);
-       c->usedump = 0;
-       c->first = NULL;
-       c->last = NULL;
-       c->active = NULL;
-
-       return c;
-}
-
-
-chain *chain_dnew(void)
-{
-       chain *c;
-       
-       c = DNEW(chain);
-       c->usedump = 1;
-       c->first = NULL;
-       c->last = NULL;
-       c->active = NULL;
-
-       return c;
-}
-
-
-void chain_free(chain *c)
-{
-       chainlink *l;
-
-       assert(!c->usedump);
-
-       l = c->first;
-       while (l) {
-               chainlink *nextl = l->next;
-               
-               FREE(l, chainlink);
-               l = nextl;      
-       }
-       
-       FREE(c, chain);
-}
-
-
-void chain_addafter(chain *c, void *element)
-{
-       chainlink *active;
-       chainlink *newlink;
-
-    active = c->active;
-
-       if (c->usedump) {
-               newlink = DNEW(chainlink);
-
-       } else {
-               newlink = NEW(chainlink);
-       }
-
-       newlink->element = element;
-       
-       if (active) {
-               newlink->next = active->next;
-               newlink->prev = active;
-               
-               active->next = newlink;
-               if (newlink->next) {
-                       newlink->next->prev = newlink;
-
-               } else {
-                       c->last = newlink;
-               }
-
-       } else {
-               newlink->next = NULL;
-               newlink->prev = NULL;
-
-               c->active = newlink;    
-               c->first = newlink;
-               c->last = newlink;
-       }
-}
-
-
-void chain_addbefore(chain *c, void *element)
-{
-       chainlink *active;
-       chainlink *newlink;
-
-    active = c->active;
-
-       if (c->usedump) {
-               newlink = DNEW(chainlink);
-
-       } else {
-               newlink = NEW(chainlink);
-       }
-       
-       newlink->element = element;
-       
-       if (active) {
-               newlink->next = active;
-               newlink->prev = active->prev;
-               
-               active->prev = newlink;
-               if (newlink->prev) {
-                       newlink->prev->next = newlink;
-
-               } else {
-                       c->first = newlink;
-               }
-
-       } else {
-               newlink->next = NULL;
-               newlink->prev = NULL;
-
-               c->active = newlink;    
-               c->first = newlink;
-               c->last = newlink;
-       }
-}
-
-
-void chain_addlast(chain *c, void *e)
-{
-       chain_last(c);
-       chain_addafter(c, e);
-}
-
-
-void chain_addfirst(chain *c, void *e)
-{
-       chain_first(c);
-       chain_addbefore(c, e);
-}
-
-
-void chain_remove(chain *c)
-{
-       chainlink *active;
-       
-       active = c->active;
-       assert(active);
-
-       if (active->next) {
-               active->next->prev = active->prev;
-
-       } else {
-               c->last = active->prev;
-       }
-       
-       if (active->prev) {
-               active->prev->next = active->next;
-
-       } else {
-               c->first = active->next;
-       }
-
-
-       if (active->prev) {
-               c->active = active->prev;
-
-       } else {
-               c->active = active->next;
-       }
-
-       if (!c->usedump)
-               FREE(active, chainlink);
-}
-
-
-void *chain_remove_go_prev(chain *c)
-{
-       chain_remove(c);
-       return chain_this(c);
-}
-
-
-
-void chain_removespecific(chain *c, void *e)
-{
-       void *ce;
-       
-       ce = chain_first(c);
-       while (ce) {
-               if (e == ce) {
-                       chain_remove(c);
-                       return;
-               }
-
-        ce = chain_next(c);
-       }
-}
-
-
-void *chain_next(chain *c)
-{
-       chainlink *active;
-       
-       active = c->active;
-
-       if (!active)
-               return NULL;
-       
-       if (active->next) {
-               c->active = active->next;
-               return c->active->element;
-       }
-               
-       return NULL;
-}
-
-
-void *chain_prev(chain *c)
-{
-       chainlink *active;
-       
-       active = c->active;
-
-       if (!active)
-               return NULL;
-       
-       if (active->prev) {
-               c->active = active->prev;
-               return c->active->element;
-       }
-
-       return NULL;
-}
-
-
-void *chain_this(chain *c)
-{
-       if (c->active)
-               return c->active->element;
-
-       return NULL;
-}
-
-
-void *chain_first(chain *c)
-{
-       c->active = c->first;
-
-       if (c -> active)
-               return c->active->element;
-
-       return NULL;
-}
-
-void *chain_last(chain *c)
-{
-       c->active = c->last;
-
-       if (c->active)
-               return c->active->element;
-
-       return NULL;
-}
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- */
diff --git a/src/toolbox/chain.h b/src/toolbox/chain.h
deleted file mode 100644 (file)
index 29ec746..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-/* toolbox/chain.h - management of doubly linked lists with external linking
-
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
-   C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
-   E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
-   J. Wenninger, Institut f. Computersprachen - TU Wien
-
-   This file is part of CACAO.
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2, or (at
-   your option) any later version.
-
-   This program is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-   02110-1301, USA.
-
-   Contact: cacao@cacaojvm.org
-
-   Authors: Reinhard Grafl
-
-
-*/
-
-
-#ifndef _CHAIN_H
-#define _CHAIN_H
-
-typedef struct chainlink {          /* structure for list element */
-       struct chainlink *next;
-       struct chainlink *prev;
-       void *element;
-} chainlink;
-
-typedef struct chain {             /* structure for list */
-       int  usedump;   
-
-       chainlink *first;
-       chainlink *last;
-       chainlink *active;
-} chain;
-
-
-/* function prototypes */
-chain *chain_new(void);
-chain *chain_dnew(void);
-void chain_free(chain *c);
-
-void chain_addafter(chain *c, void *element);
-void chain_addbefore(chain *c, void *element);
-void chain_addlast(chain *c, void *element);
-void chain_addfirst(chain *c, void *element);
-
-void chain_remove(chain *c);
-void *chain_remove_go_prev(chain *c);
-void chain_removespecific(chain *c, void *element);
-
-void *chain_next(chain *c);
-void *chain_prev(chain *c);
-void *chain_this(chain *c);
-
-void *chain_first(chain *c);
-void *chain_last(chain *c);
-
-
-/*
---------------------------- interface description ------------------------
-
-Usage of these functions for list management is possible without additional
-preparation in the element structures, as opposed to the module 'list'.
-
-Consequently, the functions are a little slower and need more memory.
-
-A new list is created with
-       chain_new
-or  chain_dnew.
-The latter allocates all additional data structures on the dump memory (faster)
-for which no explicit freeing is necessary after the processing. Care needs to
-be taken to not accidentally free parts of these structures by calling
-'dump_release' too early.
-
-After usage, a list can be freed with
-       chain_free.
-(use only if the list was created with 'chain_new')
-
-
-Adding elements is easy with:
-       chain_addafter, chain_addlast, chain_addbefore, chain_addfirst          
-       
-Search the list with:
-       chain_first, chain_last, chain_prev, chain_next, chain_this
-       
-Delete elements from the list:
-       chain_remove, chain_remove_go_prev, chain_removespecific
-       
-       
-ATTENTION: As mentioned earlier, there are no pointers to the list or to other
-nodes inside the list elements, so list elements cannot be used as pointers
-into the list. Therefore a 'cursor' is used to make one element current. Every
-insertion/deletion occurs at a position relative to this cursor.
-
-*/
-
-#endif /* _CHAIN_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:
- */
index f502fca4d8e48ad819c84b06e5ee6a1fcc9a27be..dd49f3de543a65e191c909da805d04ab9c5764df 100644 (file)
@@ -1,9 +1,7 @@
 /* src/toolbox/hashtable.c - functions for internal hashtables
 
-   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.
 
@@ -30,7 +28,7 @@
 
 #include "mm/memory.h"
 
-#include "threads/lock-common.h"
+#include "threads/mutex.hpp"
 
 #include "toolbox/hashtable.h"
 
@@ -41,7 +39,7 @@
 
    Initializes a hashtable structure and allocates memory. The
    parameter size specifies the initial size of the hashtable.
-       
+
 *******************************************************************************/
 
 void hashtable_create(hashtable *hash, u4 size)
@@ -49,13 +47,11 @@ void hashtable_create(hashtable *hash, u4 size)
        /* initialize locking pointer */
 
 #if defined(ENABLE_THREADS)
-       /* We need to seperately allocate a java_object_t here, as we
-          need to store the lock object in the new hashtable if it's
-          resized.  Otherwise we get an IllegalMonitorStateException. */
-
-       hash->header = NEW(java_object_t);
+       /* We need to seperately allocate a mutex here, as we need to
+          store the lock object in the new hashtable if it's resized.
+          Otherwise we get an IllegalMonitorStateException. */
 
-       LOCK_INIT_OBJECT_LOCK(hash->header);
+       hash->mutex   = Mutex_new();
 #endif
 
        /* set initial hash values */
@@ -89,9 +85,9 @@ hashtable *hashtable_resize(hashtable *hash, u4 size)
        /* We need to store the old lock object in the new hashtable.
           Otherwise we get an IllegalMonitorStateException. */
 
-       FREE(newhash->header, java_object_t);
+       Mutex_delete(newhash->mutex);
 
-       newhash->header  = hash->header;
+       newhash->mutex   = hash->mutex;
 #endif
 
        /* store the number of entries in the new hashtable */
index 51161b7832e64444ab72190a36bf8cabce0856d3..65b166e41defb5fcdec43d9b46ae216975b756f9 100644 (file)
@@ -34,6 +34,8 @@ typedef struct hashtable hashtable;
 #include "config.h"
 #include "vm/types.h"
 
+#include "threads/mutex.hpp"
+
 #include "vm/global.h"
 #include "vm/utf8.h"
 
@@ -93,7 +95,7 @@ hashtable.ptr-->+-------------------+
 
 struct hashtable {            
 #if defined(ENABLE_THREADS)
-       java_object_t      *header;         /* required for locking               */
+       Mutex              *mutex;          /* required for locking               */
 #endif
        u4                  size;           /* current size of the hashtable      */
        u4                  entries;        /* number of entries in the table     */
@@ -103,6 +105,10 @@ struct hashtable {
 
 /* function prototypes ********************************************************/
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /* create hashtable */
 void hashtable_create(hashtable *hash, u4 size);
 
@@ -112,6 +118,10 @@ hashtable *hashtable_resize(hashtable *hash, u4 size);
 /* frees a hashtable */
 void hashtable_free(hashtable *hash);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* _HASHTABLE_H */
 
 
diff --git a/src/toolbox/list.c b/src/toolbox/list.c
deleted file mode 100644 (file)
index 4de7222..0000000
+++ /dev/null
@@ -1,349 +0,0 @@
-/* src/toolbox/list.c - double linked list
-
-   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 <stdlib.h>
-
-#include "mm/memory.h"
-
-#include "threads/lock-common.h"
-
-#include "toolbox/list.h"
-
-
-/* list_create *****************************************************************
-
-   Allocates a new list and initializes the lock object.
-
-*******************************************************************************/
-
-list_t *list_create(int nodeoffset)
-{
-       list_t *l;
-
-       l = NEW(list_t);
-
-       LOCK_INIT_OBJECT_LOCK(l);
-
-       l->first      = NULL;
-       l->last       = NULL;
-       l->nodeoffset = nodeoffset;
-       l->size       = 0;
-
-       return l;
-}
-
-
-/* list_free *******************************************************************
-
-   Free a list.
-
-*******************************************************************************/
-
-void list_free(list_t *l)
-{
-       assert(l != NULL);
-
-       FREE(l, list_t);
-}
-
-
-/* list_create_dump ************************************************************
-
-   Allocates a new list on the dump memory.
-
-   ATTENTION: This list does NOT initialize the locking object!!!
-
-*******************************************************************************/
-
-list_t *list_create_dump(int nodeoffset)
-{
-       list_t *l;
-
-       l = DNEW(list_t);
-
-       l->first      = NULL;
-       l->last       = NULL;
-       l->nodeoffset = nodeoffset;
-       l->size       = 0;
-
-       return l;
-}
-
-
-/* list_lock *******************************************************************
-
-   Locks the list.
-
-*******************************************************************************/
-
-void list_lock(list_t *l)
-{
-       LOCK_MONITOR_ENTER(l);
-}
-
-
-/* list_unlock *****************************************************************
-
-   Unlocks the list.
-
-*******************************************************************************/
-
-void list_unlock(list_t *l)
-{
-       LOCK_MONITOR_EXIT(l);
-}
-
-
-/* list_add_first **************************************************************
-
-   Adds the element as first element.
-
-*******************************************************************************/
-
-void list_add_first(list_t *l, void *element)
-{
-       listnode_t *ln;
-
-       ln = (listnode_t *) (((uint8_t *) element) + l->nodeoffset);
-
-       if (l->first) {
-               ln->prev       = NULL;
-               ln->next       = l->first;
-               l->first->prev = ln;
-               l->first       = ln;
-       }
-       else {
-               ln->prev = NULL;
-               ln->next = NULL;
-               l->last  = ln;
-               l->first = ln;
-       }
-
-       /* Increase number of elements. */
-
-       l->size++;
-}
-
-
-/* list_add_last ***************************************************************
-
-   Adds the element as last element.
-
-*******************************************************************************/
-
-void list_add_last(list_t *l, void *element)
-{
-       listnode_t *ln;
-
-       ln = (listnode_t *) (((uint8_t *) element) + l->nodeoffset);
-
-       if (l->last) {
-               ln->prev      = l->last;
-               ln->next      = NULL;
-               l->last->next = ln;
-               l->last       = ln;
-       }
-       else {
-               ln->prev = NULL;
-               ln->next = NULL;
-               l->last  = ln;
-               l->first = ln;
-       }
-
-       /* Increase number of elements. */
-
-       l->size++;
-}
-
-
-/* list_add_before *************************************************************
-
-   Adds the element newelement to the list l before element.
-
-   [ A ] <-> [ newn ] <-> [ n ] <-> [ B ]
-
-*******************************************************************************/
-
-void list_add_before(list_t *l, void *element, void *newelement)
-{
-       listnode_t *ln;
-       listnode_t *newln;
-
-       ln    = (listnode_t *) (((uint8_t *) element) + l->nodeoffset);
-       newln = (listnode_t *) (((uint8_t *) newelement) + l->nodeoffset);
-
-       /* Set the new links. */
-
-       newln->prev = ln->prev;
-       newln->next = ln;
-
-       if (newln->prev)
-               newln->prev->next = newln;
-
-       ln->prev = newln;
-
-       /* set list's first and last if necessary */
-
-       if (l->first == ln)
-               l->first = newln;
-
-       if (l->last == ln)
-               l->last = newln;
-
-       /* Increase number of elements. */
-
-       l->size++;
-}
-
-
-/* list_remove ***************************************************************
-
-   Removes the element.
-
-*******************************************************************************/
-
-void list_remove(list_t *l, void *element)
-{
-       listnode_t *ln;
-
-       ln = (listnode_t *) (((uint8_t *) element) + l->nodeoffset);
-       
-       if (ln->next)
-               ln->next->prev = ln->prev;
-       else
-               l->last = ln->prev;
-
-       if (ln->prev)
-               ln->prev->next = ln->next;
-       else
-               l->first = ln->next;
-
-       ln->next = NULL;
-       ln->prev = NULL;
-
-       /* Decrease number of elements. */
-
-       l->size--;
-}
-
-/* list_first ******************************************************************
-
-   Returns the first element of the list.
-
-*******************************************************************************/
-
-void *list_first(list_t *l)
-{
-       void *el;
-
-       if (l->first == NULL)
-               el = NULL;
-       else
-               el = ((uint8_t *) l->first) - l->nodeoffset;
-
-       return el;
-}
-
-
-/* list_last *******************************************************************
-
-   Returns the last element of the list.
-
-*******************************************************************************/
-
-void *list_last(list_t *l)
-{
-       void *el;
-
-       if (l->last == NULL)
-               el = NULL;
-       else
-               el = ((uint8_t *) l->last) - l->nodeoffset;
-
-       return el;
-}
-
-
-/* list_next *******************************************************************
-
-   Returns the next element of element from the list.
-
-*******************************************************************************/
-
-void *list_next(list_t *l, void *element)
-{
-       listnode_t *ln;
-       void       *el;
-
-       ln = (listnode_t *) (((uint8_t *) element) + l->nodeoffset);
-
-       if (ln->next == NULL)
-               el = NULL;
-       else
-               el = ((uint8_t *) ln->next) - l->nodeoffset;
-
-       return el;
-}
-
-       
-/* list_prev *******************************************************************
-
-   Returns the previous element of element from the list.
-
-*******************************************************************************/
-
-void *list_prev(list_t *l, void *element)
-{
-       listnode_t *ln;
-       void       *el;
-
-       ln = (listnode_t *) (((uint8_t *) element) + l->nodeoffset);
-
-       if (ln->prev == NULL)
-               el = NULL;
-       else
-               el = ((uint8_t *) ln->prev) - l->nodeoffset;
-
-       return el;
-}
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- */
diff --git a/src/toolbox/list.h b/src/toolbox/list.h
deleted file mode 100644 (file)
index f93cf1b..0000000
+++ /dev/null
@@ -1,162 +0,0 @@
-/* src/toolbox/list.h - synchronized linked list
-
-   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 _LIST_H
-#define _LIST_H
-
-#include "config.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <stdint.h>
-
-#include "vm/global.h"
-
-
-/* ---------------------- interface description -----------------------------
-
-The list management with this module works like this:
-       
-       - to be used in a list, a structure must have an element of type
-         'listnode'.
-         
-       - there needs to be a structure of type 'list'.
-       
-       - the function list_init(l, nodeoffset) initializes the structure.
-         nodeoffset is the offset of the 'listnode' from the start of the
-         structure in bytes.
-         
-       - The remaining functions provide inserting, removing and searching.
-         
-This small example aims to demonstrate correct usage:
-
-
-
-       void bsp() {
-               struct node {
-                       listnode linkage;
-                       int value;
-                       } a,b,c, *el;
-                       
-               list l;
-               
-               a.value = 7;
-               b.value = 9;
-               c.value = 11;
-               
-               list_init (&l, OFFSET(struct node,linkage) );
-               list_addlast (&l, a);
-               list_addlast (&l, b);
-               list_addlast (&l, c);
-               
-               e = list_first (&l);
-               while (e) {
-                       printf ("Element: %d\n", e->value);
-                       e = list_next (&l,e);
-                       }
-       }
-       
-       
-       The output from this program should be:
-               7
-               9
-               11
-
-
-
-The reason for the usage of 'nodeoffset' is that this way, the same node can
-part of different lists (there must be one 'listnode' element for every
-distinct list).
-
-*/
-
-/* listnode_t *****************************************************************/
-
-typedef struct listnode_t listnode_t;
-
-struct listnode_t {
-       listnode_t *next;
-       listnode_t *prev;
-};
-
-
-/* list_t *********************************************************************/
-
-typedef struct list_t list_t;
-
-struct list_t {
-#if defined(ENABLE_THREADS)
-       java_object_t      lock;            /* threads lock object                */
-#endif
-       listnode_t        *first;
-       listnode_t        *last;
-       int                nodeoffset;
-       int                size;            /* number of elements in the list     */
-};
-
-
-/* function prototypes ********************************************************/
-
-list_t *list_create(int nodeoffset);
-list_t *list_create_dump(int nodeoffset);
-
-void    list_free(list_t *l);
-
-void    list_lock(list_t *l);
-void    list_unlock(list_t *l);
-
-void    list_add_first(list_t *l, void *element);
-void    list_add_last(list_t *l, void *element);
-void    list_add_before(list_t *l, void *element, void *newelement);
-
-void    list_remove(list_t *l, void *element);
-
-void   *list_first(list_t *l);
-void   *list_last(list_t *l);
-
-void   *list_next(list_t *l, void *element);
-void   *list_prev(list_t *l, void *element);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _LIST_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:
- */
diff --git a/src/toolbox/list.hpp b/src/toolbox/list.hpp
new file mode 100644 (file)
index 0000000..0ca05c8
--- /dev/null
@@ -0,0 +1,132 @@
+/* src/toolbox/list.hpp - linked list
+
+   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 _LIST_HPP
+#define _LIST_HPP
+
+#include "config.h"
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+#include <list>
+#endif
+
+#include "threads/mutex.hpp"
+
+
+#ifdef __cplusplus
+
+/**
+ * List implementation with a Mutex.
+ */
+template<class T> class List : protected std::list<T> {
+private:
+       Mutex _mutex;
+
+public:
+       virtual ~List() {}
+
+       void lock  () { _mutex.lock(); }
+       void unlock() { _mutex.unlock(); }
+
+       // make iterator of std::list visible
+       using std::list<T>::iterator;
+       using std::list<T>::reverse_iterator;
+
+       // make functions of std::list visible
+       using std::list<T>::back;
+       using std::list<T>::begin;
+       using std::list<T>::clear;
+       using std::list<T>::empty;
+       using std::list<T>::end;
+       using std::list<T>::front;
+       using std::list<T>::push_back;
+       using std::list<T>::push_front;
+       using std::list<T>::rbegin;
+       using std::list<T>::remove;
+       using std::list<T>::rend;
+       using std::list<T>::size;
+};
+
+
+// Required by DumpList.
+#include "mm/dumpmemory.hpp"
+
+
+/**
+ * List implementation with dump memory.
+ */
+template<class T> class DumpList : protected std::list<T, DumpMemoryAllocator<T> > {
+public:
+       virtual ~DumpList() {}
+
+       // make iterator of std::list visible
+       using std::list<T, DumpMemoryAllocator<T> >::iterator;
+       using std::list<T, DumpMemoryAllocator<T> >::reverse_iterator;
+
+       // make functions of std::list visible
+       using std::list<T, DumpMemoryAllocator<T> >::back;
+       using std::list<T, DumpMemoryAllocator<T> >::begin;
+       using std::list<T, DumpMemoryAllocator<T> >::clear;
+       using std::list<T, DumpMemoryAllocator<T> >::empty;
+       using std::list<T, DumpMemoryAllocator<T> >::end;
+       using std::list<T, DumpMemoryAllocator<T> >::front;
+       using std::list<T, DumpMemoryAllocator<T> >::push_back;
+       using std::list<T, DumpMemoryAllocator<T> >::push_front;
+       using std::list<T, DumpMemoryAllocator<T> >::rbegin;
+       using std::list<T, DumpMemoryAllocator<T> >::remove;
+       using std::list<T, DumpMemoryAllocator<T> >::rend;
+       using std::list<T, DumpMemoryAllocator<T> >::size;
+
+       void* operator new(size_t size) {
+               return DumpMemory::allocate(size);
+       }
+
+       void operator delete(void* p) {}
+};
+
+#else
+
+typedef struct List List;
+typedef struct DumpList DumpList;
+
+#endif
+
+#endif // _LIST_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:
+ */
index a0604b702bcae0822f3dd522f5bbb538244c7b1b..86f243869dcb720b483a70d0bbc76cefd948d221 100644 (file)
 #include "vm/utf8.h"
 
 
-/*500 is to small for eclipse traces, (builtin_trace_args, perhaps the
-buffer should be created there dynamically, if the text is longer,
-instead of setting the size for all invocations that big*/
-
-#define MAXLOGTEXT  16383 
-
 /* function prototypes ********************************************************/
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 void log_init(const char *fname);
 
 void log_start(void);
@@ -65,6 +63,10 @@ void log_message_method(const char *msg, methodinfo *m);
 #define log_text(s) log_println("%s", (s))
 #define dolog log_println
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* _LOGGING_H */
 
 
index e27647b503ebca4cb350790d002238dbd09e2f4d..c63ddf8827f91b68d35225c7f09820a02111219d 100644 (file)
@@ -63,9 +63,9 @@ struct set {
 *******************************************************************************/
 
 set *set_new(unsigned capacity) {
-       set *s = DNEW(set);
+       set *s = DumpMemory_allocate(sizeof(set));
 
-       s->elements = DMNEW(void *, capacity);
+       s->elements = DumpMemory_allocate(sizeof(void*) * capacity);
        MZERO(s->elements, void *, capacity);
        s->capacity = capacity;
        s->size = 0;
diff --git a/src/toolbox/tree.c b/src/toolbox/tree.c
deleted file mode 100644 (file)
index e76fd23..0000000
+++ /dev/null
@@ -1,230 +0,0 @@
-/* toolbox/tree.h - binary tree management
-
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
-   C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
-   E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
-   J. Wenninger, Institut f. Computersprachen - TU Wien
-
-   This file is part of CACAO.
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2, or (at
-   your option) any later version.
-
-   This program is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-   02110-1301, USA.
-
-   Contact: cacao@cacaojvm.org
-
-   Authors: Reinhard Grafl
-
-
-*/
-
-
-#include <stdio.h>
-#include <assert.h>
-
-#include "mm/memory.h"
-#include "toolbox/tree.h"
-
-
-tree *tree_new(treeelementcomperator comperator)
-{
-       tree *t = NEW(tree);
-       
-       t->usedump = 0;
-       t->comperator = comperator;
-       t->top = NULL;
-       t->active = NULL;
-               
-       return t;
-}
-
-
-tree *tree_dnew(treeelementcomperator comperator)
-{
-       tree *t = DNEW(tree);
-       
-       t->usedump = 1;
-       t->comperator = comperator;
-       t->top = NULL;
-       t->active = NULL;
-       
-       return t;
-}
-
-
-static void tree_nodefree(treenode *tn)
-{
-       if (!tn)
-               return;
-
-       tree_nodefree(tn->left);
-       tree_nodefree(tn->right);
-       FREE(tn, treenode);
-}
-
-
-void tree_free(tree *t)
-{
-       assert(!t->usedump);
-       
-       tree_nodefree(t->top);
-       FREE(t, tree);
-}
-
-
-static treenode *tree_nodeadd(tree *t, treenode *par, treenode *n, 
-                                                         void *element, void *key)
-{
-       if (!n) {
-               if (t->usedump) {
-                       n = DNEW(treenode);
-
-               } else {
-                       n = NEW(treenode);
-               }
-               
-               n->left = NULL;
-               n->right = NULL;
-               n->parent = par;
-               n->element = element;
-
-       } else {
-               if (t->comperator(key, n->element) < 0) {
-                       n->left = tree_nodeadd(t, n, n->left, element, key);
-
-               } else {
-                       n->right = tree_nodeadd(t, n, n->right, element, key);
-               }
-       }
-               
-       return n;
-}
-
-
-void tree_add(tree *t, void *element, void *key)
-{
-       t->top = tree_nodeadd(t, NULL, t->top, element, key);
-       t->active = t->top;
-}
-
-
-static treenode *tree_nodefind(tree *t, treenode *n, void *key)
-{
-       int way;
-
-       if (!n)
-               return NULL;
-
-       way = t->comperator(key, n->element);
-       if (way == 0)
-               return n;
-
-       if (way < 0) {
-               return tree_nodefind(t, n->left, key);
-
-       } else {
-               return tree_nodefind (t, n -> right, key);
-       }
-}
-
-
-void *tree_find(tree *t, void *key)
-{
-       treenode *tn = tree_nodefind(t, t->top, key);
-
-       if (!tn)
-               return NULL;
-
-       t->active = tn;
-
-       return tn->element;
-}
-
-
-
-void *tree_this(tree *t)
-{      
-       if (!t->active)
-               return NULL;
-
-       return t->active->element;
-}
-
-
-static treenode *leftmostnode(treenode *t)
-{
-       while (t->left) {
-               t = t->left;
-       }
-
-       return t;
-}
-
-
-void *tree_first(tree *t)
-{
-       treenode *a = t->top;
-
-       if (!a)
-               return NULL;
-
-       a = leftmostnode(a);
-       t->active = a;
-
-       return a->element;
-}
-
-
-void *tree_next (tree *t)
-{
-       treenode *a = t->active;
-       treenode *comefrom = NULL;
-
-       while (a) {
-               if (!a)
-                       return NULL;
-
-               if (a->left && (a->left == comefrom)) {
-                       t -> active = a;
-                       return a->element;
-               }
-       
-               if (a->right && (a->right != comefrom)) {
-                       a = leftmostnode(a->right);
-                       t -> active = a;
-                       return a->element;
-               }
-               
-               comefrom = a;
-               a = a->parent;
-       }
-
-       t->active = NULL;
-
-       return NULL;
-}
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- */
diff --git a/src/toolbox/tree.h b/src/toolbox/tree.h
deleted file mode 100644 (file)
index e031f93..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-/* toolbox/tree.h - binary tree management
-
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
-   C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
-   E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
-   J. Wenninger, Institut f. Computersprachen - TU Wien
-
-   This file is part of CACAO.
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2, or (at
-   your option) any later version.
-
-   This program is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-   02110-1301, USA.
-
-   Contact: cacao@cacaojvm.org
-
-   Authors: Reinhard Grafl
-
-
-*/
-
-
-#ifndef _TREE_H
-#define _TREE_H
-
-typedef int (*treeelementcomperator) (void *key, void * element);
-
-
-typedef struct treenode {
-       struct treenode *left,*right;
-       struct treenode *parent;
-       
-       void *element;
-} treenode;
-
-typedef struct {
-       int usedump;
-       treeelementcomperator comperator;       
-
-       treenode *top;
-       treenode *active;
-} tree;
-
-
-/* function prototypes */
-
-tree *tree_new(treeelementcomperator comperator);
-tree *tree_dnew(treeelementcomperator comperator);
-void tree_free(tree *t);
-
-void tree_add(tree *t, void *element, void *key);
-void *tree_find(tree *t, void *key);
-
-void *tree_this(tree *t);
-void *tree_first(tree *t);
-void *tree_next(tree *t);
-
-#endif /* _TREE_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:
- */
index 4952cd26fd1e60d52d42ae702f7a5e3160f87efb..659ab0eb967aaa913edacc8eb5544aad606fc82a 100644 (file)
 #ifndef _UTIL_H
 #define _UTIL_H
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #include "config.h"
 
 #include <stdarg.h>
@@ -39,6 +35,10 @@ extern "C" {
 
 /* function prototypes ********************************************************/
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 char *_Jv_getcwd(void);
 int   get_variable_message_length(const char *fmt, va_list ap);
 
index 4ec2f30d1ce894918f8d28ee266a03cdf1ab26ee..9867cc83625af1543a0d53a8a836ce61fb7ab2af 100644 (file)
@@ -29,8 +29,8 @@ SUBDIRS = jit
 
 if ENABLE_ASSERTION
 ASSERTION_SOURCES = \
-       assertion.c \
-       assertion.h
+       assertion.cpp \
+       assertion.hpp
 endif
 
 if ENABLE_CYCLES_STATS
@@ -80,12 +80,9 @@ libvm_la_SOURCES = \
        access.c \
        access.h \
        $(ANNOTATION_SOURCES) \
-       array.c \
-       array.h \
+       array.cpp \
+       array.hpp \
        $(ASSERTION_SOURCES) \
-       builtin.c \
-       builtin.h \
-       builtintable.inc \
        class.c \
        class.h \
        classcache.c \
@@ -95,8 +92,8 @@ libvm_la_SOURCES = \
        descriptor.h \
        exceptions.cpp \
        exceptions.hpp \
-       field.c \
-       field.h \
+       field.cpp \
+       field.hpp \
        finalizer.c \
        finalizer.h \
        globals.cpp \
@@ -105,11 +102,10 @@ libvm_la_SOURCES = \
        initialize.h \
        javaobjects.cpp \
        javaobjects.hpp \
-       jit_interface.h \
        linker.c \
        linker.h \
-       loader.c \
-       loader.h \
+       loader.cpp \
+       loader.hpp \
        method.c \
        method.h \
        options.c \
@@ -120,9 +116,8 @@ libvm_la_SOURCES = \
        package.hpp \
        primitive.cpp \
        primitive.hpp \
-       primitivecore.c \
-       properties.c \
-       properties.h \
+       properties.cpp \
+       properties.hpp \
        references.h \
        resolve.c \
        resolve.h \
@@ -133,10 +128,11 @@ libvm_la_SOURCES = \
        $(STATISTICS_SOURCES) \
        string.cpp \
        string.hpp \
-       suck.c \
-       suck.h \
+       suck.cpp \
+       suck.hpp \
        utf8.c \
        utf8.h \
+       vftbl.hpp \
        vm.cpp \
        vm.hpp \
        $(ZLIB_SOURCES)
index eb67440337ddd7acab9ddfd80ac403568f572172..9dd2b1e05eb51f15e1b597202b1c0e3065d6cf90 100644 (file)
 #include "native/llni.h"
 
 #include "vm/access.h"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/class.h"
 #include "vm/exceptions.hpp"
-#include "vm/field.h"
+#include "vm/field.hpp"
 #include "vm/globals.hpp"
 #include "vm/method.h"
 
index 1b90872201d610d90daf1300f56002c444b9829b..0b1def4768f6d0bdea16729c653131b0d8031af4 100644 (file)
@@ -35,7 +35,7 @@ extern "C" {
 #endif
 
 #include "vm/class.h"
-#include "vm/field.h"
+#include "vm/field.hpp"
 #include "vm/global.h"
 #include "vm/method.h"
 
index 5b3c9ce470ebddc67c95be864a67f2d850929033..b85b352a4f5154816b0f1a4cd5bd2d790ff1ee77 100644 (file)
 #include "toolbox/logging.h"
 
 #include "vm/annotation.h"
-#include "vm/array.h"
-#include "vm/builtin.h"
+#include "vm/array.hpp"
+#include "vm/jit/builtin.hpp"
 #include "vm/class.h"
-#include "vm/loader.h"
+#include "vm/loader.hpp"
 #include "vm/primitive.hpp"
-#include "vm/suck.h"
+#include "vm/suck.hpp"
 #include "vm/types.h"
 
 #if !defined(ENABLE_ANNOTATIONS)
index 38f517c5ef30d1e3cc64c8aad9fd530c82868693..2450132b2d8917a7869ba84ef3717596a605fff4 100644 (file)
 #include "vm/types.h"
 
 #include "vm/class.h"
-#include "vm/field.h"
+#include "vm/field.hpp"
 #include "vm/global.h"
-#include "vm/loader.h"
+#include "vm/loader.hpp"
 #include "vm/method.h"
 
 
 /* function prototypes ********************************************************/
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 bool annotation_load_class_attribute_runtimevisibleannotations(
        classbuffer *cb);
 
@@ -67,6 +71,10 @@ bool annotation_load_method_attribute_runtimevisibleparameterannotations(
 bool annotation_load_method_attribute_runtimeinvisibleparameterannotations(
        classbuffer *cb, methodinfo *m);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* _ANNOTATION_H */
 
 
diff --git a/src/vm/array.c b/src/vm/array.c
deleted file mode 100644 (file)
index 58fdff3..0000000
+++ /dev/null
@@ -1,396 +0,0 @@
-/* src/vm/array.c - Java array 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"
-
-#include <stdint.h>
-
-#include "native/llni.h"
-
-#include "vm/array.h"
-#include "vm/exceptions.hpp"
-#include "vm/global.h"
-#include "vm/primitive.hpp"
-#include "vm/vm.hpp"
-
-
-/* array_element_get ***********************************************************
-
-   Returns a boxed element of the given Java array.
-
-*******************************************************************************/
-
-java_handle_t *array_element_get(java_handle_t *a, int32_t index)
-{
-       vftbl_t       *v;
-       int            type;
-       imm_union      value;
-       java_handle_t *o;
-
-       if (a == NULL) {
-               exceptions_throw_nullpointerexception();
-               return NULL;
-       }
-
-       v = LLNI_vftbl_direct(a);
-
-       type = v->arraydesc->arraytype;
-
-       value = array_element_primitive_get(a, index);
-
-       o = Primitive_box(type, value);
-
-       return o;
-}
-
-
-/* array_element_set ***********************************************************
-
-   Sets a boxed element in the given Java array.
-
-*******************************************************************************/
-
-void array_element_set(java_handle_t *a, int32_t index, java_handle_t *o)
-{
-       imm_union value;
-
-       value = Primitive_unbox(o);
-
-       array_element_primitive_set(a, index, value);
-}
-
-
-/* array_element_primitive_get *************************************************
-
-   Returns a primitive element of the given Java array.
-
-*******************************************************************************/
-
-imm_union array_element_primitive_get(java_handle_t *a, int32_t index)
-{
-       vftbl_t  *v;
-       int       type;
-       imm_union value;
-
-       if (a == NULL) {
-               exceptions_throw_nullpointerexception();
-               value.a = NULL;
-               return value;
-       }
-
-       v = LLNI_vftbl_direct(a);
-
-       type = v->arraydesc->arraytype;
-
-       switch (type) {
-       case ARRAYTYPE_BOOLEAN:
-               value.i = array_booleanarray_element_get((java_handle_booleanarray_t *) a, index);
-               break;
-       case ARRAYTYPE_BYTE:
-               value.i = array_bytearray_element_get((java_handle_bytearray_t *) a,
-                                                                                         index);
-               break;
-       case ARRAYTYPE_CHAR:
-               value.i = array_chararray_element_get((java_handle_chararray_t *) a,
-                                                                                         index);
-               break;
-       case ARRAYTYPE_SHORT:
-               value.i = array_shortarray_element_get((java_handle_shortarray_t *) a,
-                                                                                          index);
-               break;
-       case ARRAYTYPE_INT:
-               value.i = array_intarray_element_get((java_handle_intarray_t *) a,
-                                                                                        index);
-               break;
-       case ARRAYTYPE_LONG:
-               value.l = array_longarray_element_get((java_handle_longarray_t *) a,
-                                                                                         index);
-               break;
-       case ARRAYTYPE_FLOAT:
-               value.f = array_floatarray_element_get((java_handle_floatarray_t *) a,
-                                                                                          index);
-               break;
-       case ARRAYTYPE_DOUBLE:
-               value.d = array_doublearray_element_get((java_handle_doublearray_t *) a,
-                                                                                               index);
-               break;
-       case ARRAYTYPE_OBJECT:
-               value.a = array_objectarray_element_get((java_handle_objectarray_t *) a,
-                                                                                               index);
-               break;
-       default:
-               vm_abort("array_element_primitive_get: invalid array element type %d",
-                                type);
-       }
-
-       return value;
-}
-
-
-/* array_element_primitive_set *************************************************
-
-   Sets a primitive element in the given Java array.
-
-*******************************************************************************/
-
-void array_element_primitive_set(java_handle_t *a, int32_t index, imm_union value)
-{
-       vftbl_t *v;
-       int      type;
-
-       if (a == NULL) {
-               exceptions_throw_nullpointerexception();
-               return;
-       }
-
-       v = LLNI_vftbl_direct(a);
-
-       type = v->arraydesc->arraytype;
-
-       switch (type) {
-       case ARRAYTYPE_BOOLEAN:
-               array_booleanarray_element_set((java_handle_booleanarray_t *) a,
-                                                                          index, value.i);
-               break;
-       case ARRAYTYPE_BYTE:
-               array_bytearray_element_set((java_handle_bytearray_t *) a,
-                                                                       index, value.i);
-               break;
-       case ARRAYTYPE_CHAR:
-               array_chararray_element_set((java_handle_chararray_t *) a,
-                                                                       index, value.i);
-               break;
-       case ARRAYTYPE_SHORT:
-               array_shortarray_element_set((java_handle_shortarray_t *) a,
-                                                                        index, value.i);
-               break;
-       case ARRAYTYPE_INT:
-               array_intarray_element_set((java_handle_intarray_t *) a,
-                                                                  index, value.i);
-               break;
-       case ARRAYTYPE_LONG:
-               array_longarray_element_set((java_handle_longarray_t *) a,
-                                                                       index, value.l);
-               break;
-       case ARRAYTYPE_FLOAT:
-               array_floatarray_element_set((java_handle_floatarray_t *) a,
-                                                                        index, value.f);
-               break;
-       case ARRAYTYPE_DOUBLE:
-               array_doublearray_element_set((java_handle_doublearray_t *) a,
-                                                                         index, value.d);
-               break;
-       case ARRAYTYPE_OBJECT:
-               array_objectarray_element_set((java_handle_objectarray_t *) a,
-                                                                         index, value.a);
-               break;
-       default:
-               vm_abort("array_element_primitive_set: invalid array element type %d",
-                                type);
-       }
-}
-
-
-/* array_xxxarray_element_get **************************************************
-
-   Returns a primitive element of the given Java array.
-
-*******************************************************************************/
-
-#define ARRAY_TYPEARRAY_ELEMENT_GET(name, type)                                \
-type array_##name##array_element_get(java_handle_##name##array_t *a, int32_t index) \
-{                                                                              \
-       type    value;                                                             \
-       int32_t size;                                                              \
-                                                                               \
-       if (a == NULL) {                                                           \
-               exceptions_throw_nullpointerexception();                               \
-               return (type) 0;                                                       \
-       }                                                                          \
-                                                                               \
-       size = LLNI_array_size(a);                                                 \
-                                                                               \
-       if ((index < 0) || (index >= size)) {                                      \
-               exceptions_throw_arrayindexoutofboundsexception();                     \
-               return (type) 0;                                                       \
-       }                                                                          \
-                                                                               \
-       value = LLNI_array_direct(a, index);                                       \
-                                                                               \
-       return value;                                                              \
-}
-
-java_handle_t *array_objectarray_element_get(java_handle_objectarray_t *a, int32_t index)
-{
-       java_handle_t *value;
-       int32_t size;
-
-       if (a == NULL) {
-               exceptions_throw_nullpointerexception();
-               return NULL;
-       }
-
-       size = LLNI_array_size(a);
-
-       if ((index < 0) || (index >= size)) {
-               exceptions_throw_arrayindexoutofboundsexception();
-               return NULL;
-       }
-
-       LLNI_CRITICAL_START;
-       value = LLNI_WRAP(LLNI_array_direct(a, index));
-       LLNI_CRITICAL_END;
-
-       return value;
-}
-
-ARRAY_TYPEARRAY_ELEMENT_GET(boolean, uint8_t)
-ARRAY_TYPEARRAY_ELEMENT_GET(byte,    int8_t)
-ARRAY_TYPEARRAY_ELEMENT_GET(char,    uint16_t)
-ARRAY_TYPEARRAY_ELEMENT_GET(short,   int16_t)
-ARRAY_TYPEARRAY_ELEMENT_GET(int,     int32_t)
-ARRAY_TYPEARRAY_ELEMENT_GET(long,    int64_t)
-ARRAY_TYPEARRAY_ELEMENT_GET(float,   float)
-ARRAY_TYPEARRAY_ELEMENT_GET(double,  double)
-
-
-/* array_xxxarray_element_set **************************************************
-
-   Sets a primitive element in the given Java array.
-
-*******************************************************************************/
-
-#define ARRAY_TYPEARRAY_ELEMENT_SET(name, type)                                \
-void array_##name##array_element_set(java_handle_##name##array_t *a, int32_t index, type value) \
-{                                                                              \
-       int32_t size;                                                              \
-                                                                               \
-       if (a == NULL) {                                                           \
-               exceptions_throw_nullpointerexception();                               \
-               return;                                                                \
-       }                                                                          \
-                                                                               \
-       size = LLNI_array_size(a);                                                 \
-                                                                               \
-       if ((index < 0) || (index >= size)) {                                      \
-               exceptions_throw_arrayindexoutofboundsexception();                     \
-               return;                                                                \
-       }                                                                          \
-                                                                               \
-       LLNI_array_direct(a, index) = value;                                       \
-}
-
-void array_objectarray_element_set(java_handle_objectarray_t *a, int32_t index, java_handle_t *value)
-{
-       int32_t size;
-
-       if (a == NULL) {
-               exceptions_throw_nullpointerexception();
-               return;
-       }
-
-       /* Sanity check. */
-
-       assert(a->header.objheader.vftbl->arraydesc->arraytype == ARRAYTYPE_OBJECT);
-
-       if (value != NULL) {
-               if (builtin_canstore(a, value) == false) {
-                       exceptions_throw_illegalargumentexception();
-                       return;
-               }
-       }
-
-       size = LLNI_array_size(a);
-
-       if ((index < 0) || (index >= size)) {
-               exceptions_throw_arrayindexoutofboundsexception();
-               return;
-       }
-
-       LLNI_CRITICAL_START;
-       LLNI_array_direct(a, index) = LLNI_UNWRAP(value);
-       LLNI_CRITICAL_END;
-}
-
-ARRAY_TYPEARRAY_ELEMENT_SET(boolean, uint8_t)
-ARRAY_TYPEARRAY_ELEMENT_SET(byte,    int8_t)
-ARRAY_TYPEARRAY_ELEMENT_SET(char,    uint16_t)
-ARRAY_TYPEARRAY_ELEMENT_SET(short,   int16_t)
-ARRAY_TYPEARRAY_ELEMENT_SET(int,     int32_t)
-ARRAY_TYPEARRAY_ELEMENT_SET(long,    int64_t)
-ARRAY_TYPEARRAY_ELEMENT_SET(float,   float)
-ARRAY_TYPEARRAY_ELEMENT_SET(double,  double)
-
-
-/* array_length_get ***********************************************************
-
-   Returns a the length of the given Java array.
-
-   ARGUMENTS:
-       a ... Java array
-
-   RETURN VALUE:
-         -1 ... exception thrown
-          >= 0 ... length of the Java array
-
-*******************************************************************************/
-
-int32_t array_length_get(java_handle_t *a)
-{
-       classinfo *c;
-       int32_t    size;
-
-       if (a == NULL) {
-               exceptions_throw_nullpointerexception();
-               return -1;
-       }
-
-       LLNI_class_get(a, c);
-
-       if (!class_is_array(c)) {
-/*             exceptions_throw_illegalargumentexception("Argument is not an array"); */
-               exceptions_throw_illegalargumentexception();
-               return -1;
-       }
-
-       size = LLNI_array_size(a);
-
-       return size;
-}
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
diff --git a/src/vm/array.cpp b/src/vm/array.cpp
new file mode 100644 (file)
index 0000000..de602db
--- /dev/null
@@ -0,0 +1,396 @@
+/* src/vm/array.cpp - Java array 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"
+
+#include <stdint.h>
+
+#include "native/llni.h"
+
+#include "vm/array.hpp"
+#include "vm/exceptions.hpp"
+#include "vm/global.h"
+#include "vm/primitive.hpp"
+#include "vm/vm.hpp"
+
+
+/* array_element_get ***********************************************************
+
+   Returns a boxed element of the given Java array.
+
+*******************************************************************************/
+
+java_handle_t *array_element_get(java_handle_t *a, int32_t index)
+{
+       vftbl_t       *v;
+       int            type;
+       imm_union      value;
+       java_handle_t *o;
+
+       if (a == NULL) {
+               exceptions_throw_nullpointerexception();
+               return NULL;
+       }
+
+       v = LLNI_vftbl_direct(a);
+
+       type = v->arraydesc->arraytype;
+
+       value = array_element_primitive_get(a, index);
+
+       o = Primitive::box(type, value);
+
+       return o;
+}
+
+
+/* array_element_set ***********************************************************
+
+   Sets a boxed element in the given Java array.
+
+*******************************************************************************/
+
+void array_element_set(java_handle_t *a, int32_t index, java_handle_t *o)
+{
+       imm_union value;
+
+       value = Primitive::unbox(o);
+
+       array_element_primitive_set(a, index, value);
+}
+
+
+/* array_element_primitive_get *************************************************
+
+   Returns a primitive element of the given Java array.
+
+*******************************************************************************/
+
+imm_union array_element_primitive_get(java_handle_t *a, int32_t index)
+{
+       vftbl_t  *v;
+       int       type;
+       imm_union value;
+
+       if (a == NULL) {
+               exceptions_throw_nullpointerexception();
+               value.a = NULL;
+               return value;
+       }
+
+       v = LLNI_vftbl_direct(a);
+
+       type = v->arraydesc->arraytype;
+
+       switch (type) {
+       case ARRAYTYPE_BOOLEAN:
+               value.i = array_booleanarray_element_get((java_handle_booleanarray_t *) a, index);
+               break;
+       case ARRAYTYPE_BYTE:
+               value.i = array_bytearray_element_get((java_handle_bytearray_t *) a,
+                                                                                         index);
+               break;
+       case ARRAYTYPE_CHAR:
+               value.i = array_chararray_element_get((java_handle_chararray_t *) a,
+                                                                                         index);
+               break;
+       case ARRAYTYPE_SHORT:
+               value.i = array_shortarray_element_get((java_handle_shortarray_t *) a,
+                                                                                          index);
+               break;
+       case ARRAYTYPE_INT:
+               value.i = array_intarray_element_get((java_handle_intarray_t *) a,
+                                                                                        index);
+               break;
+       case ARRAYTYPE_LONG:
+               value.l = array_longarray_element_get((java_handle_longarray_t *) a,
+                                                                                         index);
+               break;
+       case ARRAYTYPE_FLOAT:
+               value.f = array_floatarray_element_get((java_handle_floatarray_t *) a,
+                                                                                          index);
+               break;
+       case ARRAYTYPE_DOUBLE:
+               value.d = array_doublearray_element_get((java_handle_doublearray_t *) a,
+                                                                                               index);
+               break;
+       case ARRAYTYPE_OBJECT:
+               value.a = array_objectarray_element_get((java_handle_objectarray_t *) a,
+                                                                                               index);
+               break;
+       default:
+               vm_abort("array_element_primitive_get: invalid array element type %d",
+                                type);
+       }
+
+       return value;
+}
+
+
+/* array_element_primitive_set *************************************************
+
+   Sets a primitive element in the given Java array.
+
+*******************************************************************************/
+
+void array_element_primitive_set(java_handle_t *a, int32_t index, imm_union value)
+{
+       vftbl_t *v;
+       int      type;
+
+       if (a == NULL) {
+               exceptions_throw_nullpointerexception();
+               return;
+       }
+
+       v = LLNI_vftbl_direct(a);
+
+       type = v->arraydesc->arraytype;
+
+       switch (type) {
+       case ARRAYTYPE_BOOLEAN:
+               array_booleanarray_element_set((java_handle_booleanarray_t *) a,
+                                                                          index, value.i);
+               break;
+       case ARRAYTYPE_BYTE:
+               array_bytearray_element_set((java_handle_bytearray_t *) a,
+                                                                       index, value.i);
+               break;
+       case ARRAYTYPE_CHAR:
+               array_chararray_element_set((java_handle_chararray_t *) a,
+                                                                       index, value.i);
+               break;
+       case ARRAYTYPE_SHORT:
+               array_shortarray_element_set((java_handle_shortarray_t *) a,
+                                                                        index, value.i);
+               break;
+       case ARRAYTYPE_INT:
+               array_intarray_element_set((java_handle_intarray_t *) a,
+                                                                  index, value.i);
+               break;
+       case ARRAYTYPE_LONG:
+               array_longarray_element_set((java_handle_longarray_t *) a,
+                                                                       index, value.l);
+               break;
+       case ARRAYTYPE_FLOAT:
+               array_floatarray_element_set((java_handle_floatarray_t *) a,
+                                                                        index, value.f);
+               break;
+       case ARRAYTYPE_DOUBLE:
+               array_doublearray_element_set((java_handle_doublearray_t *) a,
+                                                                         index, value.d);
+               break;
+       case ARRAYTYPE_OBJECT:
+               array_objectarray_element_set((java_handle_objectarray_t *) a,
+                                                                         index, static_cast<java_handle_t*>(value.a));
+               break;
+       default:
+               vm_abort("array_element_primitive_set: invalid array element type %d",
+                                type);
+       }
+}
+
+
+/* array_xxxarray_element_get **************************************************
+
+   Returns a primitive element of the given Java array.
+
+*******************************************************************************/
+
+#define ARRAY_TYPEARRAY_ELEMENT_GET(name, type)                                \
+type array_##name##array_element_get(java_handle_##name##array_t *a, int32_t index) \
+{                                                                              \
+       type    value;                                                             \
+       int32_t size;                                                              \
+                                                                               \
+       if (a == NULL) {                                                           \
+               exceptions_throw_nullpointerexception();                               \
+               return (type) 0;                                                       \
+       }                                                                          \
+                                                                               \
+       size = LLNI_array_size(a);                                                 \
+                                                                               \
+       if ((index < 0) || (index >= size)) {                                      \
+               exceptions_throw_arrayindexoutofboundsexception();                     \
+               return (type) 0;                                                       \
+       }                                                                          \
+                                                                               \
+       value = LLNI_array_direct(a, index);                                       \
+                                                                               \
+       return value;                                                              \
+}
+
+java_handle_t *array_objectarray_element_get(java_handle_objectarray_t *a, int32_t index)
+{
+       java_handle_t *value;
+       int32_t size;
+
+       if (a == NULL) {
+               exceptions_throw_nullpointerexception();
+               return NULL;
+       }
+
+       size = LLNI_array_size(a);
+
+       if ((index < 0) || (index >= size)) {
+               exceptions_throw_arrayindexoutofboundsexception();
+               return NULL;
+       }
+
+       LLNI_CRITICAL_START;
+       value = LLNI_WRAP(LLNI_array_direct(a, index));
+       LLNI_CRITICAL_END;
+
+       return value;
+}
+
+ARRAY_TYPEARRAY_ELEMENT_GET(boolean, uint8_t)
+ARRAY_TYPEARRAY_ELEMENT_GET(byte,    int8_t)
+ARRAY_TYPEARRAY_ELEMENT_GET(char,    uint16_t)
+ARRAY_TYPEARRAY_ELEMENT_GET(short,   int16_t)
+ARRAY_TYPEARRAY_ELEMENT_GET(int,     int32_t)
+ARRAY_TYPEARRAY_ELEMENT_GET(long,    int64_t)
+ARRAY_TYPEARRAY_ELEMENT_GET(float,   float)
+ARRAY_TYPEARRAY_ELEMENT_GET(double,  double)
+
+
+/* array_xxxarray_element_set **************************************************
+
+   Sets a primitive element in the given Java array.
+
+*******************************************************************************/
+
+#define ARRAY_TYPEARRAY_ELEMENT_SET(name, type)                                \
+void array_##name##array_element_set(java_handle_##name##array_t *a, int32_t index, type value) \
+{                                                                              \
+       int32_t size;                                                              \
+                                                                               \
+       if (a == NULL) {                                                           \
+               exceptions_throw_nullpointerexception();                               \
+               return;                                                                \
+       }                                                                          \
+                                                                               \
+       size = LLNI_array_size(a);                                                 \
+                                                                               \
+       if ((index < 0) || (index >= size)) {                                      \
+               exceptions_throw_arrayindexoutofboundsexception();                     \
+               return;                                                                \
+       }                                                                          \
+                                                                               \
+       LLNI_array_direct(a, index) = value;                                       \
+}
+
+void array_objectarray_element_set(java_handle_objectarray_t *a, int32_t index, java_handle_t *value)
+{
+       int32_t size;
+
+       if (a == NULL) {
+               exceptions_throw_nullpointerexception();
+               return;
+       }
+
+       /* Sanity check. */
+
+       assert(a->header.objheader.vftbl->arraydesc->arraytype == ARRAYTYPE_OBJECT);
+
+       if (value != NULL) {
+               if (builtin_canstore(a, value) == false) {
+                       exceptions_throw_illegalargumentexception();
+                       return;
+               }
+       }
+
+       size = LLNI_array_size(a);
+
+       if ((index < 0) || (index >= size)) {
+               exceptions_throw_arrayindexoutofboundsexception();
+               return;
+       }
+
+       LLNI_CRITICAL_START;
+       LLNI_array_direct(a, index) = LLNI_UNWRAP(value);
+       LLNI_CRITICAL_END;
+}
+
+ARRAY_TYPEARRAY_ELEMENT_SET(boolean, uint8_t)
+ARRAY_TYPEARRAY_ELEMENT_SET(byte,    int8_t)
+ARRAY_TYPEARRAY_ELEMENT_SET(char,    uint16_t)
+ARRAY_TYPEARRAY_ELEMENT_SET(short,   int16_t)
+ARRAY_TYPEARRAY_ELEMENT_SET(int,     int32_t)
+ARRAY_TYPEARRAY_ELEMENT_SET(long,    int64_t)
+ARRAY_TYPEARRAY_ELEMENT_SET(float,   float)
+ARRAY_TYPEARRAY_ELEMENT_SET(double,  double)
+
+
+/* array_length_get ***********************************************************
+
+   Returns a the length of the given Java array.
+
+   ARGUMENTS:
+       a ... Java array
+
+   RETURN VALUE:
+         -1 ... exception thrown
+          >= 0 ... length of the Java array
+
+*******************************************************************************/
+
+int32_t array_length_get(java_handle_t *a)
+{
+       classinfo *c;
+       int32_t    size;
+
+       if (a == NULL) {
+               exceptions_throw_nullpointerexception();
+               return -1;
+       }
+
+       LLNI_class_get(a, c);
+
+       if (!class_is_array(c)) {
+/*             exceptions_throw_illegalargumentexception("Argument is not an array"); */
+               exceptions_throw_illegalargumentexception();
+               return -1;
+       }
+
+       size = LLNI_array_size(a);
+
+       return size;
+}
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
diff --git a/src/vm/array.h b/src/vm/array.h
deleted file mode 100644 (file)
index 132855c..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-/* src/vm/array.h - Java array 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.
-
-*/
-
-
-#ifndef _VM_ARRAY_H
-#define _VM_ARRAY_H
-
-#include "config.h"
-
-#include <stdint.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "vm/global.h"
-#include "vm/primitive.hpp"
-
-
-/* array types ****************************************************************/
-
-/* CAUTION: Don't change the numerical values! These constants (with
-   the exception of ARRAYTYPE_OBJECT) are used as indices in the
-   primitive type table. */
-
-#define ARRAYTYPE_INT         PRIMITIVETYPE_INT
-#define ARRAYTYPE_LONG        PRIMITIVETYPE_LONG
-#define ARRAYTYPE_FLOAT       PRIMITIVETYPE_FLOAT
-#define ARRAYTYPE_DOUBLE      PRIMITIVETYPE_DOUBLE
-#define ARRAYTYPE_BYTE        PRIMITIVETYPE_BYTE
-#define ARRAYTYPE_CHAR        PRIMITIVETYPE_CHAR
-#define ARRAYTYPE_SHORT       PRIMITIVETYPE_SHORT
-#define ARRAYTYPE_BOOLEAN     PRIMITIVETYPE_BOOLEAN
-#define ARRAYTYPE_OBJECT      PRIMITIVETYPE_VOID     /* don't use as index! */
-
-
-/* function prototypes ********************************************************/
-
-java_handle_t *array_element_get(java_handle_t *a, int32_t index);
-void           array_element_set(java_handle_t *a, int32_t index, java_handle_t *o);
-
-imm_union      array_element_primitive_get(java_handle_t *a, int32_t index);
-void           array_element_primitive_set(java_handle_t *a, int32_t index, imm_union value);
-
-uint8_t        array_booleanarray_element_get(java_handle_booleanarray_t *a, int32_t index);
-int8_t         array_bytearray_element_get(java_handle_bytearray_t *a, int32_t index);
-uint16_t       array_chararray_element_get(java_handle_chararray_t *a, int32_t index);
-int16_t        array_shortarray_element_get(java_handle_shortarray_t *a, int32_t index);
-int32_t        array_intarray_element_get(java_handle_intarray_t *a, int32_t index);
-int64_t        array_longarray_element_get(java_handle_longarray_t *a, int32_t index);
-float          array_floatarray_element_get(java_handle_floatarray_t *a, int32_t index);
-double         array_doublearray_element_get(java_handle_doublearray_t *a, int32_t index);
-java_handle_t *array_objectarray_element_get(java_handle_objectarray_t *a, int32_t index);
-
-void           array_booleanarray_element_set(java_handle_booleanarray_t *a, int32_t index, uint8_t value);
-void           array_bytearray_element_set(java_handle_bytearray_t *a, int32_t index, int8_t value);
-void           array_chararray_element_set(java_handle_chararray_t *a, int32_t index, uint16_t value);
-void           array_shortarray_element_set(java_handle_shortarray_t *a, int32_t index, int16_t value);
-void           array_intarray_element_set(java_handle_intarray_t *a, int32_t index, int32_t value);
-void           array_longarray_element_set(java_handle_longarray_t *a, int32_t index, int64_t value);
-void           array_floatarray_element_set(java_handle_floatarray_t *a, int32_t index, float value);
-void           array_doublearray_element_set(java_handle_doublearray_t *a, int32_t index, double value);
-void           array_objectarray_element_set(java_handle_objectarray_t *a, int32_t index, java_handle_t *value);
-
-int32_t        array_length_get(java_handle_t *a);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _VM_ARRAY_H */
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
diff --git a/src/vm/array.hpp b/src/vm/array.hpp
new file mode 100644 (file)
index 0000000..86f1084
--- /dev/null
@@ -0,0 +1,107 @@
+/* src/vm/array.hpp - Java array 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.
+
+*/
+
+
+#ifndef _VM_ARRAY_HPP
+#define _VM_ARRAY_HPP
+
+#include "config.h"
+
+#include <stdint.h>
+
+#include "vm/global.h"
+#include "vm/primitive.hpp"
+
+
+/* array types ****************************************************************/
+
+/* CAUTION: Don't change the numerical values! These constants (with
+   the exception of ARRAYTYPE_OBJECT) are used as indices in the
+   primitive type table. */
+
+#define ARRAYTYPE_INT         PRIMITIVETYPE_INT
+#define ARRAYTYPE_LONG        PRIMITIVETYPE_LONG
+#define ARRAYTYPE_FLOAT       PRIMITIVETYPE_FLOAT
+#define ARRAYTYPE_DOUBLE      PRIMITIVETYPE_DOUBLE
+#define ARRAYTYPE_BYTE        PRIMITIVETYPE_BYTE
+#define ARRAYTYPE_CHAR        PRIMITIVETYPE_CHAR
+#define ARRAYTYPE_SHORT       PRIMITIVETYPE_SHORT
+#define ARRAYTYPE_BOOLEAN     PRIMITIVETYPE_BOOLEAN
+#define ARRAYTYPE_OBJECT      PRIMITIVETYPE_VOID     /* don't use as index! */
+
+
+/* function prototypes ********************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+java_handle_t *array_element_get(java_handle_t *a, int32_t index);
+void           array_element_set(java_handle_t *a, int32_t index, java_handle_t *o);
+
+imm_union      array_element_primitive_get(java_handle_t *a, int32_t index);
+void           array_element_primitive_set(java_handle_t *a, int32_t index, imm_union value);
+
+uint8_t        array_booleanarray_element_get(java_handle_booleanarray_t *a, int32_t index);
+int8_t         array_bytearray_element_get(java_handle_bytearray_t *a, int32_t index);
+uint16_t       array_chararray_element_get(java_handle_chararray_t *a, int32_t index);
+int16_t        array_shortarray_element_get(java_handle_shortarray_t *a, int32_t index);
+int32_t        array_intarray_element_get(java_handle_intarray_t *a, int32_t index);
+int64_t        array_longarray_element_get(java_handle_longarray_t *a, int32_t index);
+float          array_floatarray_element_get(java_handle_floatarray_t *a, int32_t index);
+double         array_doublearray_element_get(java_handle_doublearray_t *a, int32_t index);
+java_handle_t *array_objectarray_element_get(java_handle_objectarray_t *a, int32_t index);
+
+void           array_booleanarray_element_set(java_handle_booleanarray_t *a, int32_t index, uint8_t value);
+void           array_bytearray_element_set(java_handle_bytearray_t *a, int32_t index, int8_t value);
+void           array_chararray_element_set(java_handle_chararray_t *a, int32_t index, uint16_t value);
+void           array_shortarray_element_set(java_handle_shortarray_t *a, int32_t index, int16_t value);
+void           array_intarray_element_set(java_handle_intarray_t *a, int32_t index, int32_t value);
+void           array_longarray_element_set(java_handle_longarray_t *a, int32_t index, int64_t value);
+void           array_floatarray_element_set(java_handle_floatarray_t *a, int32_t index, float value);
+void           array_doublearray_element_set(java_handle_doublearray_t *a, int32_t index, double value);
+void           array_objectarray_element_set(java_handle_objectarray_t *a, int32_t index, java_handle_t *value);
+
+int32_t        array_length_get(java_handle_t *a);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _VM_ARRAY_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:
+ */
diff --git a/src/vm/assertion.c b/src/vm/assertion.c
deleted file mode 100644 (file)
index efe40b2..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-/* src/vm/assertion.c - assertion options
-
-   Copyright (C) 2007, 2008
-   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
-
-   This file is part of CACAO.
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2, or (at
-   your option) any later version.
-
-   This program is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-   02110-1301, USA.
-
-*/
-
-
-#include "config.h"
-
-#include <stdint.h>
-#include <errno.h>
-
-#include "mm/memory.h"
-
-#include "toolbox/list.h"
-
-#include "vm/assertion.h"
-#include "vm/global.h"
-#include "vm/os.hpp"
-#include "vm/vm.hpp"
-
-
-/* -ea/-da options ************************************************************/
-
-list_t  *list_assertion_names     = (list_t *)NULL;
-int32_t  assertion_class_count    = 0;
-int32_t  assertion_package_count  = 0;
-bool     assertion_user_enabled   = false;
-bool     assertion_system_enabled = false;
-
-
-/* assertion_ea_da *************************************************************
-
-   Handle -ea:/-enableassertions: and -da:/-disableassertions: options.
-
-*******************************************************************************/
-
-void assertion_ea_da(const char *name, bool enabled)
-{
-       bool              package;
-       size_t            len;
-       char             *buf;
-       assertion_name_t *item;
-       int32_t           i;
-
-       if (name == NULL) {
-               assertion_user_enabled = enabled;
-               return;
-       }
-
-       package = false;
-       len     = os_strlen(name);
-
-       if (name[len - 1] == '/') {
-               return;
-       }
-
-       buf = os_strdup(name);
-
-       if (buf == NULL) {
-               vm_abort("assertion_ea_da: strdup failed: %s", strerror(errno));
-       }
-
-       if ((len > 2) && (strcmp(name + (len - 3), "...") == 0)) {
-               package = true;
-               assertion_package_count += 1;
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-               buf[len - 2] = '\0';
-               buf[len - 3] = '/';
-#else
-               buf[len - 3] = '\0';
-#endif
-       }
-       else {
-               assertion_class_count += 1;
-       }
-
-       len = os_strlen(buf);
-
-       for (i = 0; i < len; i++) {
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-               if (buf[i] == '.') {
-                       buf[i] = '/';
-               }
-#else
-               if (buf[i] == '/') {
-                       buf[i] = '.';
-               }
-#endif
-       }
-
-       item          = NEW(assertion_name_t);
-       item->name    = buf;
-       item->enabled = enabled;
-       item->package = package;
-
-       if (list_assertion_names == NULL) {
-               list_assertion_names = list_create(OFFSET(assertion_name_t, linkage));
-       }
-
-       list_add_last(list_assertion_names, item);
-}
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
diff --git a/src/vm/assertion.cpp b/src/vm/assertion.cpp
new file mode 100644 (file)
index 0000000..7252aa3
--- /dev/null
@@ -0,0 +1,134 @@
+/* src/vm/assertion.cpp - assertion options
+
+   Copyright (C) 2007, 2008
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+   This file is part of CACAO.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+*/
+
+
+#include "config.h"
+
+#include <stdint.h>
+
+#include <cstddef>
+
+#include "mm/memory.h"
+
+#include "toolbox/list.hpp"
+
+#include "vm/assertion.hpp"
+#include "vm/global.h"
+#include "vm/os.hpp"
+
+
+/* -ea/-da options ************************************************************/
+
+List<assertion_name_t*>* list_assertion_names = NULL;
+int32_t  assertion_class_count    = 0;
+int32_t  assertion_package_count  = 0;
+bool     assertion_user_enabled   = false;
+bool     assertion_system_enabled = false;
+
+
+/* assertion_ea_da *************************************************************
+
+   Handle -ea:/-enableassertions: and -da:/-disableassertions: options.
+
+*******************************************************************************/
+
+void assertion_ea_da(const char *name, bool enabled)
+{
+       bool              package;
+       size_t            len;
+       char             *buf;
+       assertion_name_t *item;
+
+       if (name == NULL) {
+               assertion_user_enabled = enabled;
+               return;
+       }
+
+       package = false;
+       len     = os::strlen(name);
+
+       if (name[len - 1] == '/') {
+               return;
+       }
+
+       buf = os::strdup(name);
+
+       if (buf == NULL) {
+               os::abort_errno("assertion_ea_da: strdup failed");
+       }
+
+       if ((len > 2) && (strcmp(name + (len - 3), "...") == 0)) {
+               package = true;
+               assertion_package_count += 1;
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+               buf[len - 2] = '\0';
+               buf[len - 3] = '/';
+#else
+               buf[len - 3] = '\0';
+#endif
+       }
+       else {
+               assertion_class_count += 1;
+       }
+
+       len = os::strlen(buf);
+
+       for (size_t i = 0; i < len; i++) {
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+               if (buf[i] == '.') {
+                       buf[i] = '/';
+               }
+#else
+               if (buf[i] == '/') {
+                       buf[i] = '.';
+               }
+#endif
+       }
+
+       item          = NEW(assertion_name_t);
+       item->name    = buf;
+       item->enabled = enabled;
+       item->package = package;
+
+       if (list_assertion_names == NULL) {
+               list_assertion_names = new List<assertion_name_t*>();
+       }
+
+       list_assertion_names->push_back(item);
+}
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
diff --git a/src/vm/assertion.h b/src/vm/assertion.h
deleted file mode 100644 (file)
index 20add69..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-/* src/vm/assertion.h - assertion options
-
-   Copyright (C) 2007
-   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
-
-   This file is part of CACAO.
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2, or (at
-   your option) any later version.
-
-   This program is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-   02110-1301, USA.
-
-*/
-
-
-#ifndef _ASSERTION_H
-#define _ASSERTION_H
-
-#include "config.h"
-
-#include <stdint.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "vm/global.h"
-#include "toolbox/list.h"
-
-
-typedef struct assertion_name_t assertion_name_t;
-
-struct assertion_name_t {
-       char      *name;
-       bool       enabled;
-       bool       package;
-       listnode_t linkage;
-};
-
-/* -ea/-esa/-da/-dsa options **************************************************/
-
-extern list_t  *list_assertion_names;
-extern int32_t  assertion_class_count;
-extern int32_t  assertion_package_count;
-extern bool     assertion_user_enabled;
-extern bool     assertion_system_enabled;
-
-/* function prototypes ********************************************************/
-
-void assertion_ea_da(const char *name, bool enabled);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _ASSERTION_H */
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
diff --git a/src/vm/assertion.hpp b/src/vm/assertion.hpp
new file mode 100644 (file)
index 0000000..2840b55
--- /dev/null
@@ -0,0 +1,85 @@
+/* src/vm/assertion.hpp - assertion options
+
+   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 _ASSERTION_HPP
+#define _ASSERTION_HPP
+
+#include "config.h"
+
+#include <stdint.h>
+
+#include "toolbox/list.hpp"
+
+
+typedef struct assertion_name_t assertion_name_t;
+
+struct assertion_name_t {
+       char      *name;
+       bool       enabled;
+       bool       package;
+/*     listnode_t linkage; */
+};
+
+/* -ea/-esa/-da/-dsa options **************************************************/
+
+#ifdef __cplusplus
+extern List<assertion_name_t*>*   list_assertion_names;
+#else
+extern List*   list_assertion_names;
+#endif
+
+extern int32_t assertion_class_count;
+extern int32_t assertion_package_count;
+extern bool    assertion_user_enabled;
+extern bool    assertion_system_enabled;
+
+/* function prototypes ********************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void assertion_ea_da(const char *name, bool enabled);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _ASSERTION_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:
+ */
diff --git a/src/vm/builtin.c b/src/vm/builtin.c
deleted file mode 100644 (file)
index 3464171..0000000
+++ /dev/null
@@ -1,2513 +0,0 @@
-/* src/vm/builtin.c - functions for unsupported operations
-
-   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.
-
-   Contains C functions for JavaVM Instructions that cannot be
-   translated to machine language directly. Consequently, the
-   generated machine code for these instructions contains function
-   calls instead of machine instructions, using the C calling
-   convention.
-
-*/
-
-
-#include "config.h"
-
-#include <assert.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/time.h>
-
-#include "vm/types.h"
-
-#include "arch.h"
-#include "md-abi.h"
-
-#include "fdlibm/fdlibm.h"
-#if defined(__CYGWIN__) && defined(Bias)
-# undef Bias
-#endif
-
-#include "mm/gc.hpp"
-#include "mm/memory.h"
-
-#include "native/jni.h"
-#include "native/llni.h"
-
-#include "threads/lock-common.h"
-#include "threads/thread.hpp"
-
-#include "toolbox/logging.h"
-#include "toolbox/util.h"
-
-#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"
-
-#if defined(ENABLE_VMLOG)
-#include <vmlog_cacao.h>
-#endif
-
-
-/* include builtin tables *****************************************************/
-
-#include "vm/builtintable.inc"
-
-
-CYCLES_STATS_DECLARE(builtin_new         ,100,5)
-CYCLES_STATS_DECLARE(builtin_overhead    , 80,1)
-
-
-/*============================================================================*/
-/* BUILTIN TABLE MANAGEMENT FUNCTIONS                                         */
-/*============================================================================*/
-
-/* builtintable_init ***********************************************************
-
-   Parse the descriptors of builtin functions and create the parsed
-   descriptors.
-
-*******************************************************************************/
-
-static bool builtintable_init(void)
-{
-       descriptor_pool    *descpool;
-       builtintable_entry *bte;
-       methodinfo         *m;
-       int32_t             dumpmarker;
-
-       /* mark start of dump memory area */
-
-       DMARKER;
-
-       /* create a new descriptor pool */
-
-       descpool = descriptor_pool_new(class_java_lang_Object);
-
-       /* add some entries we need */
-
-       if (!descriptor_pool_add_class(descpool, utf_java_lang_Object))
-               return false;
-
-       if (!descriptor_pool_add_class(descpool, utf_java_lang_Class))
-               return false;
-
-       /* first add all descriptors to the pool */
-
-       for (bte = builtintable_internal; bte->fp != NULL; bte++) {
-               bte->name       = utf_new_char(bte->cname);
-               bte->descriptor = utf_new_char(bte->cdescriptor);
-
-               if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
-                       /* release dump area */
-
-                       DRELEASE;
-
-                       return false;
-               }
-       }
-
-       for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
-               bte->descriptor = utf_new_char(bte->cdescriptor);
-
-               if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
-                       DRELEASE;
-                       return false;
-               }
-       }
-
-       for (bte = builtintable_function; bte->fp != NULL; bte++) {
-               bte->classname  = utf_new_char(bte->cclassname);
-               bte->name       = utf_new_char(bte->cname);
-               bte->descriptor = utf_new_char(bte->cdescriptor);
-
-               if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
-                       DRELEASE;
-                       return false;
-               }
-       }
-
-       /* create the class reference table */
-
-       (void) descriptor_pool_create_classrefs(descpool, NULL);
-
-       /* allocate space for the parsed descriptors */
-
-       descriptor_pool_alloc_parsed_descriptors(descpool);
-
-       /* Now parse all descriptors.  NOTE: builtin-functions are treated
-          like static methods (no `this' pointer). */
-
-       for (bte = builtintable_internal; bte->fp != NULL; bte++) {
-               bte->md =
-                       descriptor_pool_parse_method_descriptor(descpool,
-                                                                                                       bte->descriptor,
-                                                                                                       ACC_STATIC | ACC_METHOD_BUILTIN,
-                                                                                                       NULL);
-
-               /* generate a builtin stub if we need one */
-
-               if (bte->flags & BUILTINTABLE_FLAG_STUB) {
-                       m = method_new_builtin(bte);
-                       codegen_generate_stub_builtin(m, bte);
-               }
-       }
-
-       for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
-               bte->md =
-                       descriptor_pool_parse_method_descriptor(descpool,
-                                                                                                       bte->descriptor,
-                                                                                                       ACC_STATIC | ACC_METHOD_BUILTIN,
-                                                                                                       NULL);
-
-               /* no stubs should be needed for this table */
-
-               assert(!bte->flags & BUILTINTABLE_FLAG_STUB);
-       }
-
-       for (bte = builtintable_function; bte->fp != NULL; bte++) {
-               bte->md =
-                       descriptor_pool_parse_method_descriptor(descpool,
-                                                                                                       bte->descriptor,
-                                                                                                       ACC_STATIC | ACC_METHOD_BUILTIN,
-                                                                                                       NULL);
-
-               /* generate a builtin stub if we need one */
-
-               if (bte->flags & BUILTINTABLE_FLAG_STUB) {
-                       m = method_new_builtin(bte);
-                       codegen_generate_stub_builtin(m, bte);
-               }
-       }
-
-       /* release dump area */
-
-       DRELEASE;
-
-       return true;
-}
-
-
-/* builtintable_comparator *****************************************************
-
-   qsort comparator for the automatic builtin table.
-
-*******************************************************************************/
-
-static int builtintable_comparator(const void *a, const void *b)
-{
-       builtintable_entry *bte1;
-       builtintable_entry *bte2;
-
-       bte1 = (builtintable_entry *) a;
-       bte2 = (builtintable_entry *) b;
-
-       return (bte1->opcode < bte2->opcode) ? -1 : (bte1->opcode > bte2->opcode);
-}
-
-
-/* builtintable_sort_automatic *************************************************
-
-   Sorts the automatic builtin table.
-
-*******************************************************************************/
-
-static void builtintable_sort_automatic(void)
-{
-       s4 entries;
-
-       /* calculate table size statically (`- 1' comment see builtintable.inc) */
-
-       entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
-
-       qsort(builtintable_automatic, entries, sizeof(builtintable_entry),
-                 builtintable_comparator);
-}
-
-
-/* builtin_init ****************************************************************
-
-   Initialize the global table of builtin functions.
-
-*******************************************************************************/
-
-bool builtin_init(void)
-{
-       TRACESUBSYSTEMINITIALIZATION("builtin_init");
-
-       /* initialize the builtin tables */
-
-       if (!builtintable_init())
-               return false;
-
-       /* sort builtin tables */
-
-       builtintable_sort_automatic();
-
-       return true;
-}
-
-
-/* builtintable_get_by_key *****************************************************
-
-   Returns a key for the given builtintable_entry object which is suitable
-   for retrieving the instance again by calling builtintable_get_by_key.
-
-   The key can be regarded fixed between multiple runs of the JVM.
-
-*******************************************************************************/
-
-s4 builtintable_get_key(builtintable_entry *bte)
-{
-       s4 entries;
-/*
-       int i;
-       entries = sizeof(builtintable_internal) / sizeof(builtintable_entry) - 1;
-       for (i = 0; i < entries; i++)
-               if (&builtintable_internal[i] == bte)
-                       return i + 1;
-
-       entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
-       for (i = 0; i < entries; i++)
-               if (&builtintable_automatic[i] == bte)
-                       return -i;
-
-       entries = sizeof(builtintable_function) / sizeof(builtintable_entry) - 1;
-       for (i = 0; i < entries; i++)
-               if (&builtintable_function[i] == bte)
-                       return -1000 - i;
-*/
-
-       entries = sizeof(builtintable_internal) / sizeof(builtintable_entry) - 1;
-       if (&builtintable_internal[0] <= bte
-               && &builtintable_internal[entries - 1] >= bte)
-       {
-               return (s4) (bte - &builtintable_internal[0]) + 1;
-       }
-
-       entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
-       if (&builtintable_automatic[0] <= bte
-               && &builtintable_automatic[entries - 1] >= bte)
-       {
-               return -(s4) (bte - &builtintable_automatic[0]);
-       }
-
-       entries = sizeof(builtintable_function) / sizeof(builtintable_entry) - 1;
-       if (&builtintable_function[0] <= bte
-               && &builtintable_function[entries - 1] >= bte)
-       {
-               return -1000 - (s4) (bte - &builtintable_function[0]);
-       }
-
-       /* builtintable_entry is not in our tables. */
-       assert (0);
-
-       return 0;
-}
-
-/* builtintable_get_by_key *****************************************************
-
-   Retrieves an entry in the internal and automatic builtin functions tables
-   using a key that was retrived previously with builtintable_get_key()
-
-*******************************************************************************/
-
-builtintable_entry *builtintable_get_by_key(s4 key)
-{
-       /* If key is positive it is the index into builtintable_internal. If it is
-        * negative it is the index into builtintable_automatic. If it is <= -1000
-     * it is the index into builtintable_function.
-     */
-       return (key > 0)
-               ? &builtintable_internal[key - 1]
-               : (key > -1000 ? &builtintable_automatic[-key] : &builtintable_function[-(1000 + key)]);
-}
-
-/* builtintable_get_internal ***************************************************
-
-   Finds an entry in the builtintable for internal functions and
-   returns the a pointer to the structure.
-
-*******************************************************************************/
-
-builtintable_entry *builtintable_get_internal(functionptr fp)
-{
-       builtintable_entry *bte;
-
-       for (bte = builtintable_internal; bte->fp != NULL; bte++) {
-               if (bte->fp == fp)
-                       return bte;
-       }
-
-       return NULL;
-}
-
-
-/* builtintable_get_automatic **************************************************
-
-   Finds an entry in the builtintable for functions which are replaced
-   automatically and returns the a pointer to the structure.
-
-*******************************************************************************/
-
-builtintable_entry *builtintable_get_automatic(s4 opcode)
-{
-       builtintable_entry *first;
-       builtintable_entry *last;
-       builtintable_entry *middle;
-       s4                  half;
-       s4                  entries;
-
-       /* calculate table size statically (`- 1' comment see builtintable.inc) */
-
-       entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
-
-       first = builtintable_automatic;
-       last = builtintable_automatic + entries;
-
-       while (entries > 0) {
-               half = entries / 2;
-               middle = first + half;
-
-               if (middle->opcode < opcode) {
-                       first = middle + 1;
-                       entries -= half + 1;
-               }
-               else
-                       entries = half;
-       }
-
-       return (first != last ? first : NULL);
-}
-
-
-/* builtintable_replace_function ***********************************************
-
-   XXX
-
-*******************************************************************************/
-
-#if defined(ENABLE_JIT)
-bool builtintable_replace_function(void *iptr_)
-{
-       constant_FMIref    *mr;
-       builtintable_entry *bte;
-       instruction        *iptr;
-
-       iptr = (instruction *) iptr_; /* twisti will kill me ;) */
-
-       /* get name and descriptor of the function */
-
-       switch (iptr->opc) {
-       case ICMD_INVOKESTATIC:
-               /* The instruction MUST be resolved, otherwise we run into
-                  lazy loading troubles.  Anyway, we should/can only replace
-                  very VM-close functions. */
-
-               if (INSTRUCTION_IS_UNRESOLVED(iptr))
-                       return false;
-
-               mr = iptr->sx.s23.s3.fmiref;
-               break;  
-
-       default:
-               return false;
-       }
-
-       /* search the function table */
-
-       for (bte = builtintable_function; bte->fp != NULL; bte++) {
-               if ((METHODREF_CLASSNAME(mr) == bte->classname) &&
-                       (mr->name                == bte->name) &&
-                       (mr->descriptor          == bte->descriptor)) {
-
-                       /* set the values in the instruction */
-
-                       iptr->opc           = bte->opcode;
-                       iptr->sx.s23.s3.bte = bte;
-
-                       if (bte->flags & BUILTINTABLE_FLAG_EXCEPTION)
-                               iptr->flags.bits |= INS_FLAG_CHECK;
-                       else
-                               iptr->flags.bits &= ~INS_FLAG_CHECK;
-
-                       return true;
-               }
-       }
-
-       return false;
-}
-#endif /* defined(ENABLE_JIT) */
-
-
-/*============================================================================*/
-/* INTERNAL BUILTIN FUNCTIONS                                                 */
-/*============================================================================*/
-
-/* builtin_instanceof **********************************************************
-
-   Checks if an object is an instance of some given class (or subclass
-   of that class). If class is an interface, checks if the interface
-   is implemented.
-
-   RETURN VALUE:
-     1......o is an instance of class or implements the interface
-     0......otherwise or if o == NULL
-
-   NOTE: This builtin can be called from NATIVE code only.
-
-*******************************************************************************/
-
-bool builtin_instanceof(java_handle_t *o, classinfo *c)
-{
-       classinfo *oc;
-
-       if (o == NULL)
-               return 0;
-
-       LLNI_class_get(o, oc);
-
-       return class_isanysubclass(oc, c);
-}
-
-
-
-/* builtin_checkcast ***********************************************************
-
-   The same as builtin_instanceof but with the exception
-   that 1 is returned when (o == NULL).
-
-   NOTE: This builtin can be called from NATIVE code only.
-
-*******************************************************************************/
-
-bool builtin_checkcast(java_handle_t *o, classinfo *c)
-{
-       classinfo *oc;
-
-       if (o == NULL)
-               return 1;
-
-       LLNI_class_get(o, oc);
-
-       if (class_isanysubclass(oc, c))
-               return 1;
-
-       return 0;
-}
-
-
-/* builtin_descriptorscompatible ***********************************************
-
-   Checks if two array type descriptors are assignment compatible.
-
-   RETURN VALUE:
-      1......target = desc is possible
-      0......otherwise
-                       
-*******************************************************************************/
-
-static bool builtin_descriptorscompatible(arraydescriptor *desc, arraydescriptor *target)
-{
-       if (desc == target)
-               return 1;
-
-       if (desc->arraytype != target->arraytype)
-               return 0;
-
-       if (desc->arraytype != ARRAYTYPE_OBJECT)
-               return 1;
-       
-       /* {both arrays are arrays of references} */
-
-       if (desc->dimension == target->dimension) {
-               if (!desc->elementvftbl)
-                       return 0;
-               /* an array which contains elements of interface types is
-           allowed to be casted to Object (JOWENN)*/
-
-               if ((desc->elementvftbl->baseval < 0) &&
-                       (target->elementvftbl->baseval == 1))
-                       return 1;
-
-               return class_isanysubclass(desc->elementvftbl->clazz,
-                                                                  target->elementvftbl->clazz);
-       }
-
-       if (desc->dimension < target->dimension)
-               return 0;
-
-       /* {desc has higher dimension than target} */
-
-       return class_isanysubclass(pseudo_class_Arraystub,
-                                                          target->elementvftbl->clazz);
-}
-
-
-/* builtin_arraycheckcast ******************************************************
-
-   Checks if an object is really a subtype of the requested array
-   type.  The object has to be an array to begin with. For simple
-   arrays (int, short, double, etc.) the types have to match exactly.
-   For arrays of objects, the type of elements in the array has to be
-   a subtype (or the same type) of the requested element type. For
-   arrays of arrays (which in turn can again be arrays of arrays), the
-   types at the lowest level have to satisfy the corresponding sub
-   class relation.
-
-   NOTE: This is a FAST builtin and can be called from JIT code only.
-
-*******************************************************************************/
-
-bool builtin_fast_arraycheckcast(java_object_t *o, classinfo *targetclass)
-{
-       arraydescriptor *desc;
-
-       if (o == NULL)
-               return 1;
-
-       desc = o->vftbl->arraydesc;
-
-       if (desc == NULL)
-               return 0;
-       return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc);
-}
-
-
-/* builtin_fast_arrayinstanceof ************************************************
-
-   NOTE: This is a FAST builtin and can be called from JIT code only.
-
-*******************************************************************************/
-
-bool builtin_fast_arrayinstanceof(java_object_t *o, classinfo *targetclass)
-{
-       if (o == NULL)
-               return 0;
-
-       return builtin_fast_arraycheckcast(o, targetclass);
-}
-
-
-/* builtin_arrayinstanceof *****************************************************
-
-   NOTE: This builtin can be called from NATIVE code only.
-
-*******************************************************************************/
-
-bool builtin_arrayinstanceof(java_handle_t *h, classinfo *targetclass)
-{
-       bool result;
-
-       LLNI_CRITICAL_START;
-
-       result = builtin_fast_arrayinstanceof(LLNI_UNWRAP(h), targetclass);
-
-       LLNI_CRITICAL_END;
-
-       return result;
-}
-
-
-/* builtin_throw_exception *****************************************************
-
-   Sets the exception pointer with the thrown exception and prints some
-   debugging information.
-   
-   NOTE: This is a FAST builtin and can be called from JIT code,
-   or from asm_vm_call_method.
-
-*******************************************************************************/
-
-void *builtin_throw_exception(java_object_t *xptr)
-{
-#if !defined(NDEBUG)
-       /* print exception trace */
-
-       if (opt_TraceExceptions)
-               trace_exception_builtin(xptr);
-#endif /* !defined(NDEBUG) */
-
-       /* actually set the exception */
-
-       exceptions_set_exception(LLNI_QUICKWRAP(xptr));
-
-       /* Return a NULL pointer.  This is required for vm_call_method to
-          check for an exception.  This is for convenience. */
-
-       return NULL;
-}
-
-
-/* builtin_retrieve_exception **************************************************
-
-   Gets and clears the exception pointer of the current thread.
-
-   RETURN VALUE:
-      the exception object, or NULL if no exception was thrown.
-
-   NOTE: This is a FAST builtin and can be called from JIT code,
-   or from the signal handlers.
-
-*******************************************************************************/
-
-java_object_t *builtin_retrieve_exception(void)
-{
-       java_handle_t *h;
-       java_object_t *o;
-
-       /* actually get and clear the exception */
-
-       h = exceptions_get_and_clear_exception();
-       o = LLNI_UNWRAP(h);
-
-       return o;
-}
-
-
-/* builtin_canstore ************************************************************
-
-   Checks, if an object can be stored in an array.
-
-   RETURN VALUE:
-      1......possible
-      0......otherwise (throws an ArrayStoreException)
-
-   NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
-
-*******************************************************************************/
-
-bool builtin_canstore(java_handle_objectarray_t *oa, java_handle_t *o)
-{
-       bool result;
-
-       LLNI_CRITICAL_START;
-
-       result = builtin_fast_canstore(LLNI_DIRECT(oa), LLNI_UNWRAP(o));
-
-       LLNI_CRITICAL_END;
-
-       /* if not possible, throw an exception */
-
-       if (result == 0)
-               exceptions_throw_arraystoreexception();
-
-       return result;
-}
-
-
-/* builtin_fast_canstore *******************************************************
-
-   Checks, if an object can be stored in an array.
-
-   RETURN VALUE:
-      1......possible
-      0......otherwise (no exception thrown!)
-
-   NOTE: This is a FAST builtin and can be called from JIT code only.
-
-*******************************************************************************/
-
-bool builtin_fast_canstore(java_objectarray_t *oa, java_object_t *o)
-{
-       arraydescriptor *desc;
-       arraydescriptor *valuedesc;
-       vftbl_t         *componentvftbl;
-       vftbl_t         *valuevftbl;
-       int32_t          baseval;
-       uint32_t         diffval;
-       bool             result;
-
-       if (o == NULL)
-               return 1;
-
-       /* The following is guaranteed (by verifier checks):
-        *
-        *     *) oa->...vftbl->arraydesc != NULL
-        *     *) oa->...vftbl->arraydesc->componentvftbl != NULL
-        *     *) o->vftbl is not an interface vftbl
-        */
-
-       desc           = oa->header.objheader.vftbl->arraydesc;
-       componentvftbl = desc->componentvftbl;
-       valuevftbl     = o->vftbl;
-       valuedesc      = valuevftbl->arraydesc;
-
-       if ((desc->dimension - 1) == 0) {
-               /* {oa is a one-dimensional array} */
-               /* {oa is an array of references} */
-               
-               if (valuevftbl == componentvftbl)
-                       return 1;
-
-               LOCK_MONITOR_ENTER(linker_classrenumber_lock);
-
-               baseval = componentvftbl->baseval;
-
-               if (baseval <= 0) {
-                       /* an array of interface references */
-
-                       result = ((valuevftbl->interfacetablelength > -baseval) &&
-                                         (valuevftbl->interfacetable[baseval] != NULL));
-               }
-               else {
-                       diffval = valuevftbl->baseval - componentvftbl->baseval;
-                       result  = diffval <= (uint32_t) componentvftbl->diffval;
-               }
-
-               LOCK_MONITOR_EXIT(linker_classrenumber_lock);
-       }
-       else if (valuedesc == NULL) {
-               /* {oa has dimension > 1} */
-               /* {componentvftbl->arraydesc != NULL} */
-
-               /* check if o is an array */
-
-               return 0;
-       }
-       else {
-               /* {o is an array} */
-
-               result = builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
-       }
-
-       /* return result */
-
-       return result;
-}
-
-
-/* This is an optimized version where a is guaranteed to be one-dimensional */
-bool builtin_fast_canstore_onedim(java_objectarray_t *a, java_object_t *o)
-{
-       arraydescriptor *desc;
-       vftbl_t         *elementvftbl;
-       vftbl_t         *valuevftbl;
-       int32_t          baseval;
-       uint32_t         diffval;
-       bool             result;
-       
-       if (o == NULL)
-               return 1;
-
-       /* The following is guaranteed (by verifier checks):
-        *
-        *     *) a->...vftbl->arraydesc != NULL
-        *     *) a->...vftbl->arraydesc->elementvftbl != NULL
-        *     *) a->...vftbl->arraydesc->dimension == 1
-        *     *) o->vftbl is not an interface vftbl
-        */
-
-       desc = a->header.objheader.vftbl->arraydesc;
-    elementvftbl = desc->elementvftbl;
-       valuevftbl = o->vftbl;
-
-       /* {a is a one-dimensional array} */
-       
-       if (valuevftbl == elementvftbl)
-               return 1;
-
-       LOCK_MONITOR_ENTER(linker_classrenumber_lock);
-
-       baseval = elementvftbl->baseval;
-
-       if (baseval <= 0) {
-               /* an array of interface references */
-               result = ((valuevftbl->interfacetablelength > -baseval) &&
-                                 (valuevftbl->interfacetable[baseval] != NULL));
-       }
-       else {
-               diffval = valuevftbl->baseval - elementvftbl->baseval;
-               result  = diffval <= (uint32_t) elementvftbl->diffval;
-       }
-
-       LOCK_MONITOR_EXIT(linker_classrenumber_lock);
-
-       return result;
-}
-
-
-/* This is an optimized version where a is guaranteed to be a
- * one-dimensional array of a class type */
-bool builtin_fast_canstore_onedim_class(java_objectarray_t *a, java_object_t *o)
-{
-       vftbl_t  *elementvftbl;
-       vftbl_t  *valuevftbl;
-       uint32_t  diffval;
-       bool      result;
-       
-       if (o == NULL)
-               return 1;
-
-       /* The following is guaranteed (by verifier checks):
-        *
-        *     *) a->...vftbl->arraydesc != NULL
-        *     *) a->...vftbl->arraydesc->elementvftbl != NULL
-        *     *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
-        *     *) a->...vftbl->arraydesc->dimension == 1
-        *     *) o->vftbl is not an interface vftbl
-        */
-
-    elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
-       valuevftbl = o->vftbl;
-
-       /* {a is a one-dimensional array} */
-       
-       if (valuevftbl == elementvftbl)
-               return 1;
-
-       LOCK_MONITOR_ENTER(linker_classrenumber_lock);
-
-       diffval = valuevftbl->baseval - elementvftbl->baseval;
-       result  = diffval <= (uint32_t) elementvftbl->diffval;
-
-       LOCK_MONITOR_EXIT(linker_classrenumber_lock);
-
-       return result;
-}
-
-
-/* builtin_new *****************************************************************
-
-   Creates a new instance of class c on the heap.
-
-   RETURN VALUE:
-      pointer to the object, or NULL if no memory is available
-
-   NOTE: This builtin can be called from NATIVE code only.
-
-*******************************************************************************/
-
-java_handle_t *builtin_new(classinfo *c)
-{
-       java_handle_t *o;
-#if defined(ENABLE_RT_TIMING)
-       struct timespec time_start, time_end;
-#endif
-#if defined(ENABLE_CYCLES_STATS)
-       u8 cycles_start, cycles_end;
-#endif
-
-       RT_TIMING_GET_TIME(time_start);
-       CYCLES_STATS_GET(cycles_start);
-
-       /* is the class loaded */
-
-       assert(c->state & CLASS_LOADED);
-
-       /* check if we can instantiate this class */
-
-       if (c->flags & ACC_ABSTRACT) {
-               exceptions_throw_instantiationerror(c);
-               return NULL;
-       }
-
-       /* is the class linked */
-
-       if (!(c->state & CLASS_LINKED))
-               if (!link_class(c))
-                       return NULL;
-
-       if (!(c->state & CLASS_INITIALIZED)) {
-#if !defined(NDEBUG)
-               if (initverbose)
-                       log_message_class("Initialize class (from builtin_new): ", c);
-#endif
-
-               if (!initialize_class(c))
-                       return NULL;
-       }
-
-       o = heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
-                                  c->finalizer, true);
-
-       if (!o)
-               return NULL;
-
-#if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
-       /* XXX this is only a dirty hack to make Boehm work with handles */
-
-       o = LLNI_WRAP((java_object_t *) o);
-#endif
-
-       LLNI_vftbl_direct(o) = c->vftbl;
-
-#if defined(ENABLE_THREADS)
-       lock_init_object_lock(LLNI_DIRECT(o));
-#endif
-
-       CYCLES_STATS_GET(cycles_end);
-       RT_TIMING_GET_TIME(time_end);
-
-       CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
-       RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
-
-       return o;
-}
-
-#if defined(ENABLE_ESCAPE_REASON)
-java_handle_t *builtin_escape_reason_new(classinfo *c) {
-       print_escape_reasons();
-       return builtin_java_new(c);
-}
-#endif
-
-#if defined(ENABLE_TLH)
-java_handle_t *builtin_tlh_new(classinfo *c)
-{
-       java_handle_t *o;
-# if defined(ENABLE_RT_TIMING)
-       struct timespec time_start, time_end;
-# endif
-# if defined(ENABLE_CYCLES_STATS)
-       u8 cycles_start, cycles_end;
-# endif
-
-       RT_TIMING_GET_TIME(time_start);
-       CYCLES_STATS_GET(cycles_start);
-
-       /* is the class loaded */
-
-       assert(c->state & CLASS_LOADED);
-
-       /* check if we can instantiate this class */
-
-       if (c->flags & ACC_ABSTRACT) {
-               exceptions_throw_instantiationerror(c);
-               return NULL;
-       }
-
-       /* is the class linked */
-
-       if (!(c->state & CLASS_LINKED))
-               if (!link_class(c))
-                       return NULL;
-
-       if (!(c->state & CLASS_INITIALIZED)) {
-# if !defined(NDEBUG)
-               if (initverbose)
-                       log_message_class("Initialize class (from builtin_new): ", c);
-# endif
-
-               if (!initialize_class(c))
-                       return NULL;
-       }
-
-       /*
-       o = tlh_alloc(&(THREADOBJECT->tlh), c->instancesize);
-       */
-       o = NULL;
-
-       if (o == NULL) {
-               o = heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
-                                          c->finalizer, true);
-       }
-
-       if (!o)
-               return NULL;
-
-# if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
-       /* XXX this is only a dirty hack to make Boehm work with handles */
-
-       o = LLNI_WRAP((java_object_t *) o);
-# endif
-
-       LLNI_vftbl_direct(o) = c->vftbl;
-
-# if defined(ENABLE_THREADS)
-       lock_init_object_lock(LLNI_DIRECT(o));
-# endif
-
-       CYCLES_STATS_GET(cycles_end);
-       RT_TIMING_GET_TIME(time_end);
-
-/*
-       CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
-       RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
-*/
-
-       return o;
-}
-#endif
-
-
-/* builtin_java_new ************************************************************
-
-   NOTE: This is a SLOW builtin and can be called from JIT code only.
-
-*******************************************************************************/
-
-java_handle_t *builtin_java_new(java_handle_t *clazz)
-{
-       return builtin_new(LLNI_classinfo_unwrap(clazz));
-}
-
-
-/* builtin_fast_new ************************************************************
-
-   Creates a new instance of class c on the heap.
-
-   RETURN VALUE:
-      pointer to the object, or NULL if no fast return
-      is possible for any reason.
-
-   NOTE: This is a FAST builtin and can be called from JIT code only.
-
-*******************************************************************************/
-
-java_object_t *builtin_fast_new(classinfo *c)
-{
-       java_object_t *o;
-#if defined(ENABLE_RT_TIMING)
-       struct timespec time_start, time_end;
-#endif
-#if defined(ENABLE_CYCLES_STATS)
-       u8 cycles_start, cycles_end;
-#endif
-
-       RT_TIMING_GET_TIME(time_start);
-       CYCLES_STATS_GET(cycles_start);
-
-       /* is the class loaded */
-
-       assert(c->state & CLASS_LOADED);
-
-       /* check if we can instantiate this class */
-
-       if (c->flags & ACC_ABSTRACT)
-               return NULL;
-
-       /* is the class linked */
-
-       if (!(c->state & CLASS_LINKED))
-               return NULL;
-
-       if (!(c->state & CLASS_INITIALIZED))
-               return NULL;
-
-       o = heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
-                                  c->finalizer, false);
-
-       if (!o)
-               return NULL;
-
-       o->vftbl = c->vftbl;
-
-#if defined(ENABLE_THREADS)
-       lock_init_object_lock(o);
-#endif
-
-       CYCLES_STATS_GET(cycles_end);
-       RT_TIMING_GET_TIME(time_end);
-
-       CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
-       RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
-
-       return o;
-}
-
-
-/* builtin_newarray ************************************************************
-
-   Creates an array with the given vftbl on the heap. This function
-   takes as class argument an array class.
-
-   RETURN VALUE:
-      pointer to the array or NULL if no memory is available
-
-   NOTE: This builtin can be called from NATIVE code only.
-
-*******************************************************************************/
-
-java_handle_t *builtin_newarray(int32_t size, classinfo *arrayclass)
-{
-       arraydescriptor *desc;
-       s4               dataoffset;
-       s4               componentsize;
-       s4               actualsize;
-       java_handle_t   *a;
-#if defined(ENABLE_RT_TIMING)
-       struct timespec time_start, time_end;
-#endif
-
-       RT_TIMING_GET_TIME(time_start);
-
-       desc          = arrayclass->vftbl->arraydesc;
-       dataoffset    = desc->dataoffset;
-       componentsize = desc->componentsize;
-
-       if (size < 0) {
-               exceptions_throw_negativearraysizeexception();
-               return NULL;
-       }
-
-       actualsize = dataoffset + size * componentsize;
-
-       /* check for overflow */
-
-       if (((u4) actualsize) < ((u4) size)) {
-               exceptions_throw_outofmemoryerror();
-               return NULL;
-       }
-
-       a = heap_alloc(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL, true);
-
-       if (a == NULL)
-               return NULL;
-
-#if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
-       /* XXX this is only a dirty hack to make Boehm work with handles */
-
-       a = LLNI_WRAP((java_object_t *) a);
-#endif
-
-       LLNI_vftbl_direct(a) = arrayclass->vftbl;
-
-#if defined(ENABLE_THREADS)
-       lock_init_object_lock(LLNI_DIRECT(a));
-#endif
-
-       LLNI_array_size(a) = size;
-
-       RT_TIMING_GET_TIME(time_end);
-       RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_ARRAY);
-
-       return a;
-}
-
-
-/* builtin_java_newarray *******************************************************
-
-   NOTE: This is a SLOW builtin and can be called from JIT code only.
-
-*******************************************************************************/
-
-java_handle_t *builtin_java_newarray(int32_t size, java_handle_t *arrayclazz)
-{
-       return builtin_newarray(size, LLNI_classinfo_unwrap(arrayclazz));
-}
-
-
-/* builtin_anewarray ***********************************************************
-
-   Creates an array of references to the given class type on the heap.
-
-   RETURN VALUE:
-      pointer to the array or NULL if no memory is
-      available
-
-   NOTE: This builtin can be called from NATIVE code only.
-
-*******************************************************************************/
-
-java_handle_objectarray_t *builtin_anewarray(int32_t size, classinfo *componentclass)
-{
-       classinfo *arrayclass;
-       
-       /* is class loaded */
-
-       assert(componentclass->state & CLASS_LOADED);
-
-       /* is class linked */
-
-       if (!(componentclass->state & CLASS_LINKED))
-               if (!link_class(componentclass))
-                       return NULL;
-
-       arrayclass = class_array_of(componentclass, true);
-
-       if (!arrayclass)
-               return NULL;
-
-       return (java_handle_objectarray_t *) builtin_newarray(size, arrayclass);
-}
-
-
-/* builtin_newarray_type ****************************************************
-
-   Creates an array of [type]s on the heap.
-       
-   RETURN VALUE:
-      pointer to the array or NULL if no memory is available
-
-   NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
-
-*******************************************************************************/
-
-#define BUILTIN_NEWARRAY_TYPE(type, arraytype)                             \
-java_handle_##type##array_t *builtin_newarray_##type(int32_t size)              \
-{                                                                          \
-       return (java_handle_##type##array_t *)                                 \
-               builtin_newarray(size, primitivetype_table[arraytype].arrayclass); \
-}
-
-BUILTIN_NEWARRAY_TYPE(boolean, ARRAYTYPE_BOOLEAN)
-BUILTIN_NEWARRAY_TYPE(byte,    ARRAYTYPE_BYTE)
-BUILTIN_NEWARRAY_TYPE(char,    ARRAYTYPE_CHAR)
-BUILTIN_NEWARRAY_TYPE(short,   ARRAYTYPE_SHORT)
-BUILTIN_NEWARRAY_TYPE(int,     ARRAYTYPE_INT)
-BUILTIN_NEWARRAY_TYPE(long,    ARRAYTYPE_LONG)
-BUILTIN_NEWARRAY_TYPE(float,   ARRAYTYPE_FLOAT)
-BUILTIN_NEWARRAY_TYPE(double,  ARRAYTYPE_DOUBLE)
-
-
-/* builtin_multianewarray_intern ***********************************************
-
-   Creates a multi-dimensional array on the heap. The dimensions are
-   passed in an array of longs.
-
-   ARGUMENTS:
-      n.............number of dimensions to create
-      arrayclass....the array class
-      dims..........array containing the size of each dimension to create
-
-   RETURN VALUE:
-      pointer to the array or NULL if no memory is available
-
-******************************************************************************/
-
-static java_handle_t *builtin_multianewarray_intern(int n,
-                                                                                                       classinfo *arrayclass,
-                                                                                                       long *dims)
-{
-       s4             size;
-       java_handle_t *a;
-       classinfo     *componentclass;
-       s4             i;
-
-       /* create this dimension */
-
-       size = (s4) dims[0];
-       a = builtin_newarray(size, arrayclass);
-
-       if (!a)
-               return NULL;
-
-       /* if this is the last dimension return */
-
-       if (!--n)
-               return a;
-
-       /* get the class of the components to create */
-
-       componentclass = arrayclass->vftbl->arraydesc->componentvftbl->clazz;
-
-       /* The verifier guarantees that the dimension count is in the range. */
-
-       /* create the component arrays */
-
-       for (i = 0; i < size; i++) {
-               java_handle_t *ea =
-#if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
-                       /* we save an s4 to a s8 slot, 8-byte aligned */
-
-                       builtin_multianewarray_intern(n, componentclass, dims + 2);
-#else
-                       builtin_multianewarray_intern(n, componentclass, dims + 1);
-#endif
-
-               if (!ea)
-                       return NULL;
-
-               array_objectarray_element_set((java_handle_objectarray_t *) a, i, ea);
-       }
-
-       return a;
-}
-
-
-/* builtin_multianewarray ******************************************************
-
-   Wrapper for builtin_multianewarray_intern which checks all
-   dimensions before we start allocating.
-
-   NOTE: This is a SLOW builtin and can be called from JIT code only.
-
-******************************************************************************/
-
-java_handle_objectarray_t *builtin_multianewarray(int n,
-                                                                                                 java_handle_t *arrayclazz,
-                                                                                                 long *dims)
-{
-       classinfo *c;
-       s4         i;
-       s4         size;
-
-       /* check all dimensions before doing anything */
-
-       for (i = 0; i < n; i++) {
-#if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
-               /* we save an s4 to a s8 slot, 8-byte aligned */
-               size = (s4) dims[i * 2];
-#else
-               size = (s4) dims[i];
-#endif
-
-               if (size < 0) {
-                       exceptions_throw_negativearraysizeexception();
-                       return NULL;
-               }
-       }
-
-       c = LLNI_classinfo_unwrap(arrayclazz);
-
-       /* now call the real function */
-
-       return (java_handle_objectarray_t *)
-               builtin_multianewarray_intern(n, c, dims);
-}
-
-
-/* builtin_verbosecall_enter ***************************************************
-
-   Print method call with arguments for -verbose:call.
-
-   XXX: Remove mew once all archs use the new tracer!
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-#ifdef TRACE_ARGS_NUM
-void builtin_verbosecall_enter(s8 a0, s8 a1,
-# if TRACE_ARGS_NUM >= 4
-                                                          s8 a2, s8 a3,
-# endif
-# if TRACE_ARGS_NUM >= 6
-                                                          s8 a4, s8 a5,
-# endif
-# if TRACE_ARGS_NUM == 8
-                                                          s8 a6, s8 a7,
-# endif
-                                                          methodinfo *m)
-{
-       log_text("builtin_verbosecall_enter: Do not call me anymore!");
-}
-#endif
-#endif /* !defined(NDEBUG) */
-
-
-/* builtin_verbosecall_exit ****************************************************
-
-   Print method exit for -verbose:call.
-
-   XXX: Remove mew once all archs use the new tracer!
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m)
-{
-       log_text("builtin_verbosecall_exit: Do not call me anymore!");
-}
-#endif /* !defined(NDEBUG) */
-
-
-/*============================================================================*/
-/* MISCELLANEOUS MATHEMATICAL HELPER FUNCTIONS                                */
-/*============================================================================*/
-
-/*********** Functions for integer divisions *****************************
-       On some systems (eg. DEC ALPHA), integer division is not supported by the
-       CPU. These helper functions implement the missing functionality.
-
-******************************************************************************/
-
-#if !SUPPORT_DIVISION || defined(DISABLE_GC)
-s4 builtin_idiv(s4 a, s4 b)
-{
-       s4 c;
-
-       c = a / b;
-
-       return c;
-}
-
-s4 builtin_irem(s4 a, s4 b)
-{
-       s4 c;
-
-       c = a % b;
-
-       return c;
-}
-#endif /* !SUPPORT_DIVISION || defined(DISABLE_GC) */
-
-
-/* functions for long arithmetics **********************************************
-
-   On systems where 64 bit Integers are not supported by the CPU,
-   these functions are needed.
-
-******************************************************************************/
-
-#if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
-s8 builtin_ladd(s8 a, s8 b)
-{
-       s8 c;
-
-#if U8_AVAILABLE
-       c = a + b; 
-#else
-       c = builtin_i2l(0);
-#endif
-
-       return c;
-}
-
-s8 builtin_lsub(s8 a, s8 b)
-{
-       s8 c;
-
-#if U8_AVAILABLE
-       c = a - b; 
-#else
-       c = builtin_i2l(0);
-#endif
-
-       return c;
-}
-
-s8 builtin_lneg(s8 a)
-{
-       s8 c;
-
-#if U8_AVAILABLE
-       c = -a;
-#else
-       c = builtin_i2l(0);
-#endif
-
-       return c;
-}
-#endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
-
-
-#if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
-s8 builtin_lmul(s8 a, s8 b)
-{
-       s8 c;
-
-#if U8_AVAILABLE
-       c = a * b; 
-#else
-       c = builtin_i2l(0);
-#endif
-
-       return c;
-}
-#endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
-
-
-#if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) || defined (DISABLE_GC)
-s8 builtin_ldiv(s8 a, s8 b)
-{
-       s8 c;
-
-#if U8_AVAILABLE
-       c = a / b; 
-#else
-       c = builtin_i2l(0);
-#endif
-
-       return c;
-}
-
-s8 builtin_lrem(s8 a, s8 b)
-{
-       s8 c;
-
-#if U8_AVAILABLE
-       c = a % b; 
-#else
-       c = builtin_i2l(0);
-#endif
-
-       return c;
-}
-#endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
-
-
-#if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
-s8 builtin_lshl(s8 a, s4 b)
-{
-       s8 c;
-
-#if U8_AVAILABLE
-       c = a << (b & 63);
-#else
-       c = builtin_i2l(0);
-#endif
-
-       return c;
-}
-
-s8 builtin_lshr(s8 a, s4 b)
-{
-       s8 c;
-
-#if U8_AVAILABLE
-       c = a >> (b & 63);
-#else
-       c = builtin_i2l(0);
-#endif
-
-       return c;
-}
-
-s8 builtin_lushr(s8 a, s4 b)
-{
-       s8 c;
-
-#if U8_AVAILABLE
-       c = ((u8) a) >> (b & 63);
-#else
-       c = builtin_i2l(0);
-#endif
-
-       return c;
-}
-#endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
-
-
-#if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
-s8 builtin_land(s8 a, s8 b)
-{
-       s8 c;
-
-#if U8_AVAILABLE
-       c = a & b; 
-#else
-       c = builtin_i2l(0);
-#endif
-
-       return c;
-}
-
-s8 builtin_lor(s8 a, s8 b)
-{
-       s8 c;
-
-#if U8_AVAILABLE
-       c = a | b; 
-#else
-       c = builtin_i2l(0);
-#endif
-
-       return c;
-}
-
-s8 builtin_lxor(s8 a, s8 b) 
-{
-       s8 c;
-
-#if U8_AVAILABLE
-       c = a ^ b; 
-#else
-       c = builtin_i2l(0);
-#endif
-
-       return c;
-}
-#endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
-
-
-#if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
-s4 builtin_lcmp(s8 a, s8 b)
-{ 
-#if U8_AVAILABLE
-       if (a < b)
-               return -1;
-
-       if (a > b)
-               return 1;
-
-       return 0;
-#else
-       return 0;
-#endif
-}
-#endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
-
-
-/* functions for unsupported floating instructions ****************************/
-
-/* used to convert FLT_xxx defines into float values */
-
-static inline float intBitsToFloat(s4 i)
-{
-       imm_union imb;
-
-       imb.i = i;
-       return imb.f;
-}
-
-
-/* used to convert DBL_xxx defines into double values */
-
-static inline float longBitsToDouble(s8 l)
-{
-       imm_union imb;
-
-       imb.l = l;
-       return imb.d;
-}
-
-
-#if !SUPPORT_FLOAT
-float builtin_fadd(float a, float b)
-{
-       if (isnanf(a)) return intBitsToFloat(FLT_NAN);
-       if (isnanf(b)) return intBitsToFloat(FLT_NAN);
-       if (finitef(a)) {
-               if (finitef(b))
-                       return a + b;
-               else
-                       return b;
-       }
-       else {
-               if (finitef(b))
-                       return a;
-               else {
-                       if (copysignf(1.0, a) == copysignf(1.0, b))
-                               return a;
-                       else
-                               return intBitsToFloat(FLT_NAN);
-               }
-       }
-}
-
-
-float builtin_fsub(float a, float b)
-{
-       return builtin_fadd(a, builtin_fneg(b));
-}
-
-
-float builtin_fmul(float a, float b)
-{
-       if (isnanf(a)) return intBitsToFloat(FLT_NAN);
-       if (isnanf(b)) return intBitsToFloat(FLT_NAN);
-       if (finitef(a)) {
-               if (finitef(b)) return a * b;
-               else {
-                       if (a == 0) return intBitsToFloat(FLT_NAN);
-                       else return copysignf(b, copysignf(1.0, b)*a);
-               }
-       }
-       else {
-               if (finitef(b)) {
-                       if (b == 0) return intBitsToFloat(FLT_NAN);
-                       else return copysignf(a, copysignf(1.0, a)*b);
-               }
-               else {
-                       return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
-               }
-       }
-}
-
-
-/* builtin_ddiv ****************************************************************
-
-   Implementation as described in VM Spec.
-
-*******************************************************************************/
-
-float builtin_fdiv(float a, float b)
-{
-       if (finitef(a)) {
-               if (finitef(b)) {
-                       /* If neither value1' nor value2' is NaN, the sign of the result */
-                       /* is positive if both values have the same sign, negative if the */
-                       /* values have different signs. */
-
-                       return a / b;
-
-               } else {
-                       if (isnanf(b)) {
-                               /* If either value1' or value2' is NaN, the result is NaN. */
-
-                               return intBitsToFloat(FLT_NAN);
-
-                       } else {
-                               /* Division of a finite value by an infinity results in a */
-                               /* signed zero, with the sign-producing rule just given. */
-
-                               /* is sign equal? */
-
-                               if (copysignf(1.0, a) == copysignf(1.0, b))
-                                       return 0.0;
-                               else
-                                       return -0.0;
-                       }
-               }
-
-       } else {
-               if (isnanf(a)) {
-                       /* If either value1' or value2' is NaN, the result is NaN. */
-
-                       return intBitsToFloat(FLT_NAN);
-
-               } else if (finitef(b)) {
-                       /* Division of an infinity by a finite value results in a signed */
-                       /* infinity, with the sign-producing rule just given. */
-
-                       /* is sign equal? */
-
-                       if (copysignf(1.0, a) == copysignf(1.0, b))
-                               return intBitsToFloat(FLT_POSINF);
-                       else
-                               return intBitsToFloat(FLT_NEGINF);
-
-               } else {
-                       /* Division of an infinity by an infinity results in NaN. */
-
-                       return intBitsToFloat(FLT_NAN);
-               }
-       }
-}
-
-
-float builtin_fneg(float a)
-{
-       if (isnanf(a)) return a;
-       else {
-               if (finitef(a)) return -a;
-               else return copysignf(a, -copysignf(1.0, a));
-       }
-}
-#endif /* !SUPPORT_FLOAT */
-
-
-#if !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP)
-s4 builtin_fcmpl(float a, float b)
-{
-       if (isnanf(a))
-               return -1;
-
-       if (isnanf(b))
-               return -1;
-
-       if (!finitef(a) || !finitef(b)) {
-               a = finitef(a) ? 0 : copysignf(1.0,     a);
-               b = finitef(b) ? 0 : copysignf(1.0, b);
-       }
-
-       if (a > b)
-               return 1;
-
-       if (a == b)
-               return 0;
-
-       return -1;
-}
-
-
-s4 builtin_fcmpg(float a, float b)
-{
-       if (isnanf(a)) return 1;
-       if (isnanf(b)) return 1;
-       if (!finitef(a) || !finitef(b)) {
-               a = finitef(a) ? 0 : copysignf(1.0, a);
-               b = finitef(b) ? 0 : copysignf(1.0, b);
-       }
-       if (a > b) return 1;
-       if (a == b) return 0;
-       return -1;
-}
-#endif /* !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP) */
-
-
-float builtin_frem(float a, float b)
-{
-       return fmodf(a, b);
-}
-
-
-/* functions for unsupported double instructions ******************************/
-
-#if !SUPPORT_DOUBLE
-double builtin_dadd(double a, double b)
-{
-       if (isnan(a)) return longBitsToDouble(DBL_NAN);
-       if (isnan(b)) return longBitsToDouble(DBL_NAN);
-       if (finite(a)) {
-               if (finite(b)) return a + b;
-               else return b;
-       }
-       else {
-               if (finite(b)) return a;
-               else {
-                       if (copysign(1.0, a)==copysign(1.0, b)) return a;
-                       else return longBitsToDouble(DBL_NAN);
-               }
-       }
-}
-
-
-double builtin_dsub(double a, double b)
-{
-       return builtin_dadd(a, builtin_dneg(b));
-}
-
-
-double builtin_dmul(double a, double b)
-{
-       if (isnan(a)) return longBitsToDouble(DBL_NAN);
-       if (isnan(b)) return longBitsToDouble(DBL_NAN);
-       if (finite(a)) {
-               if (finite(b)) return a * b;
-               else {
-                       if (a == 0) return longBitsToDouble(DBL_NAN);
-                       else return copysign(b, copysign(1.0, b) * a);
-               }
-       }
-       else {
-               if (finite(b)) {
-                       if (b == 0) return longBitsToDouble(DBL_NAN);
-                       else return copysign(a, copysign(1.0, a) * b);
-               }
-               else {
-                       return copysign(a, copysign(1.0, a) * copysign(1.0, b));
-               }
-       }
-}
-
-
-/* builtin_ddiv ****************************************************************
-
-   Implementation as described in VM Spec.
-
-*******************************************************************************/
-
-double builtin_ddiv(double a, double b)
-{
-       if (finite(a)) {
-               if (finite(b)) {
-                       /* If neither value1' nor value2' is NaN, the sign of the result */
-                       /* is positive if both values have the same sign, negative if the */
-                       /* values have different signs. */
-
-                       return a / b;
-
-               } else {
-                       if (isnan(b)) {
-                               /* If either value1' or value2' is NaN, the result is NaN. */
-
-                               return longBitsToDouble(DBL_NAN);
-
-                       } else {
-                               /* Division of a finite value by an infinity results in a */
-                               /* signed zero, with the sign-producing rule just given. */
-
-                               /* is sign equal? */
-
-                               if (copysign(1.0, a) == copysign(1.0, b))
-                                       return 0.0;
-                               else
-                                       return -0.0;
-                       }
-               }
-
-       } else {
-               if (isnan(a)) {
-                       /* If either value1' or value2' is NaN, the result is NaN. */
-
-                       return longBitsToDouble(DBL_NAN);
-
-               } else if (finite(b)) {
-                       /* Division of an infinity by a finite value results in a signed */
-                       /* infinity, with the sign-producing rule just given. */
-
-                       /* is sign equal? */
-
-                       if (copysign(1.0, a) == copysign(1.0, b))
-                               return longBitsToDouble(DBL_POSINF);
-                       else
-                               return longBitsToDouble(DBL_NEGINF);
-
-               } else {
-                       /* Division of an infinity by an infinity results in NaN. */
-
-                       return longBitsToDouble(DBL_NAN);
-               }
-       }
-}
-
-
-/* builtin_dneg ****************************************************************
-
-   Implemented as described in VM Spec.
-
-*******************************************************************************/
-
-double builtin_dneg(double a)
-{
-       if (isnan(a)) {
-               /* If the operand is NaN, the result is NaN (recall that NaN has no */
-               /* sign). */
-
-               return a;
-
-       } else {
-               if (finite(a)) {
-                       /* If the operand is a zero, the result is the zero of opposite */
-                       /* sign. */
-
-                       return -a;
-
-               } else {
-                       /* If the operand is an infinity, the result is the infinity of */
-                       /* opposite sign. */
-
-                       return copysign(a, -copysign(1.0, a));
-               }
-       }
-}
-#endif /* !SUPPORT_DOUBLE */
-
-
-#if !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP)
-s4 builtin_dcmpl(double a, double b)
-{
-       if (isnan(a))
-               return -1;
-
-       if (isnan(b))
-               return -1;
-
-       if (!finite(a) || !finite(b)) {
-               a = finite(a) ? 0 : copysign(1.0, a);
-               b = finite(b) ? 0 : copysign(1.0, b);
-       }
-
-       if (a > b)
-               return 1;
-
-       if (a == b)
-               return 0;
-
-       return -1;
-}
-
-
-s4 builtin_dcmpg(double a, double b)
-{
-       if (isnan(a))
-               return 1;
-
-       if (isnan(b))
-               return 1;
-
-       if (!finite(a) || !finite(b)) {
-               a = finite(a) ? 0 : copysign(1.0, a);
-               b = finite(b) ? 0 : copysign(1.0, b);
-       }
-
-       if (a > b)
-               return 1;
-
-       if (a == b)
-               return 0;
-
-       return -1;
-}
-#endif /* !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP) */
-
-
-double builtin_drem(double a, double b)
-{
-       return fmod(a, b);
-}
-
-
-/* conversion operations ******************************************************/
-
-#if 0
-s8 builtin_i2l(s4 i)
-{
-#if U8_AVAILABLE
-       return i;
-#else
-       s8 v;
-       v.high = 0;
-       v.low = i;
-       return v;
-#endif
-}
-
-s4 builtin_l2i(s8 l)
-{
-#if U8_AVAILABLE
-       return (s4) l;
-#else
-       return l.low;
-#endif
-}
-#endif
-
-
-#if !(SUPPORT_FLOAT && SUPPORT_I2F)
-float builtin_i2f(s4 a)
-{
-       float f = (float) a;
-       return f;
-}
-#endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
-
-
-#if !(SUPPORT_DOUBLE && SUPPORT_I2D)
-double builtin_i2d(s4 a)
-{
-       double d = (double) a;
-       return d;
-}
-#endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
-
-
-#if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
-float builtin_l2f(s8 a)
-{
-#if U8_AVAILABLE
-       float f = (float) a;
-       return f;
-#else
-       return 0.0;
-#endif
-}
-#endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
-
-
-#if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
-double builtin_l2d(s8 a)
-{
-#if U8_AVAILABLE
-       double d = (double) a;
-       return d;
-#else
-       return 0.0;
-#endif
-}
-#endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
-
-
-#if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
-s4 builtin_f2i(float a) 
-{
-       s4 i;
-
-       i = builtin_d2i((double) a);
-
-       return i;
-
-       /*      float f;
-       
-               if (isnanf(a))
-               return 0;
-               if (finitef(a)) {
-               if (a > 2147483647)
-               return 2147483647;
-               if (a < (-2147483648))
-               return (-2147483648);
-               return (s4) a;
-               }
-               f = copysignf((float) 1.0, a);
-               if (f > 0)
-               return 2147483647;
-               return (-2147483648); */
-}
-#endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
-
-
-#if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) || defined(DISABLE_GC)
-s8 builtin_f2l(float a)
-{
-       s8 l;
-
-       l = builtin_d2l((double) a);
-
-       return l;
-
-       /*      float f;
-       
-               if (finitef(a)) {
-               if (a > 9223372036854775807L)
-               return 9223372036854775807L;
-               if (a < (-9223372036854775808L))
-               return (-9223372036854775808L);
-               return (s8) a;
-               }
-               if (isnanf(a))
-               return 0;
-               f = copysignf((float) 1.0, a);
-               if (f > 0)
-               return 9223372036854775807L;
-               return (-9223372036854775808L); */
-}
-#endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
-
-
-#if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
-s4 builtin_d2i(double a) 
-{ 
-       double d;
-       
-       if (finite(a)) {
-               if (a >= 2147483647)
-                       return 2147483647;
-               if (a <= (-2147483647-1))
-                       return (-2147483647-1);
-               return (s4) a;
-       }
-       if (isnan(a))
-               return 0;
-       d = copysign(1.0, a);
-       if (d > 0)
-               return 2147483647;
-       return (-2147483647-1);
-}
-#endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
-
-
-#if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) || defined(DISABLE_GC)
-s8 builtin_d2l(double a)
-{
-       double d;
-       
-       if (finite(a)) {
-               if (a >= 9223372036854775807LL)
-                       return 9223372036854775807LL;
-               if (a <= (-9223372036854775807LL-1))
-                       return (-9223372036854775807LL-1);
-               return (s8) a;
-       }
-       if (isnan(a))
-               return 0;
-       d = copysign(1.0, a);
-       if (d > 0)
-               return 9223372036854775807LL;
-       return (-9223372036854775807LL-1);
-}
-#endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
-
-
-#if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
-double builtin_f2d(float a)
-{
-       if (finitef(a)) return (double) a;
-       else {
-               if (isnanf(a))
-                       return longBitsToDouble(DBL_NAN);
-               else
-                       return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
-       }
-}
-
-float builtin_d2f(double a)
-{
-       if (finite(a))
-               return (float) a;
-       else {
-               if (isnan(a))
-                       return intBitsToFloat(FLT_NAN);
-               else
-                       return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
-       }
-}
-#endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
-
-
-/*============================================================================*/
-/* AUTOMATICALLY REPLACED FUNCTIONS                                           */
-/*============================================================================*/
-
-/* builtin_arraycopy ***********************************************************
-
-   Builtin for java.lang.System.arraycopy.
-
-   NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
-
-*******************************************************************************/
-
-void builtin_arraycopy(java_handle_t *src, s4 srcStart,
-                                          java_handle_t *dest, s4 destStart, s4 len)
-{
-       arraydescriptor *sdesc;
-       arraydescriptor *ddesc;
-       s4               i;
-
-       if ((src == NULL) || (dest == NULL)) {
-               exceptions_throw_nullpointerexception();
-               return;
-       }
-
-       sdesc = LLNI_vftbl_direct(src)->arraydesc;
-       ddesc = LLNI_vftbl_direct(dest)->arraydesc;
-
-       if (!sdesc || !ddesc || (sdesc->arraytype != ddesc->arraytype)) {
-               exceptions_throw_arraystoreexception();
-               return;
-       }
-
-       // Check if offsets and length are positive.
-       if ((srcStart < 0) || (destStart < 0) || (len < 0)) {
-               exceptions_throw_arrayindexoutofboundsexception();
-               return;
-       }
-
-       // Check if ranges are valid.
-       if ((((uint32_t) srcStart  + (uint32_t) len) > (uint32_t) LLNI_array_size(src)) ||
-               (((uint32_t) destStart + (uint32_t) len) > (uint32_t) LLNI_array_size(dest))) {
-               exceptions_throw_arrayindexoutofboundsexception();
-               return;
-       }
-
-       // Special case.
-       if (len == 0) {
-               return;
-       }
-
-       if (sdesc->componentvftbl == ddesc->componentvftbl) {
-               /* We copy primitive values or references of exactly the same type */
-
-               s4 dataoffset = sdesc->dataoffset;
-               s4 componentsize = sdesc->componentsize;
-
-               LLNI_CRITICAL_START;
-
-               MMOVE(((u1 *) LLNI_DIRECT(dest)) + dataoffset + componentsize * destStart,
-                         ((u1 *) LLNI_DIRECT(src))  + dataoffset + componentsize * srcStart,
-                         u1, (size_t) len * componentsize);
-
-               LLNI_CRITICAL_END;
-       }
-       else {
-               /* We copy references of different type */
-
-               java_handle_objectarray_t *oas = (java_handle_objectarray_t *) src;
-               java_handle_objectarray_t *oad = (java_handle_objectarray_t *) dest;
-               if (destStart <= srcStart) {
-                       for (i = 0; i < len; i++) {
-                               java_handle_t *o;
-
-                               o = array_objectarray_element_get(oas, srcStart + i);
-
-                               if (!builtin_canstore(oad, o))
-                                       return;
-
-                               array_objectarray_element_set(oad, destStart + i, o);
-                       }
-               }
-               else {
-                       /* XXX this does not completely obey the specification!
-                          If an exception is thrown only the elements above the
-                          current index have been copied. The specification
-                          requires that only the elements *below* the current
-                          index have been copied before the throw. */
-
-                       for (i = len - 1; i >= 0; i--) {
-                               java_handle_t *o;
-
-                               o = array_objectarray_element_get(oas, srcStart + i);
-
-                               if (!builtin_canstore(oad, o))
-                                       return;
-
-                               array_objectarray_element_set(oad, destStart + i, o);
-                       }
-               }
-       }
-}
-
-
-/* builtin_nanotime ************************************************************
-
-   Return the current time in nanoseconds.
-
-*******************************************************************************/
-
-s8 builtin_nanotime(void)
-{
-       struct timeval tv;
-       s8             usecs;
-
-       if (gettimeofday(&tv, NULL) == -1)
-               vm_abort("gettimeofday failed: %s", strerror(errno));
-
-       usecs = (s8) tv.tv_sec * (1000 * 1000) + (s8) tv.tv_usec;
-
-       return usecs * 1000;
-}
-
-
-/* builtin_currenttimemillis ***************************************************
-
-   Return the current time in milliseconds.
-
-*******************************************************************************/
-
-s8 builtin_currenttimemillis(void)
-{
-       s8 msecs;
-
-       msecs = builtin_nanotime() / 1000 / 1000;
-
-       return msecs;
-}
-
-
-/* builtin_clone ***************************************************************
-
-   Function for cloning objects or arrays.
-
-   NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
-
-*******************************************************************************/
-
-java_handle_t *builtin_clone(void *env, java_handle_t *o)
-{
-       arraydescriptor *ad;
-       u4               size;
-       classinfo       *c;
-       java_handle_t   *co;                /* cloned object header               */
-
-       /* get the array descriptor */
-
-       ad = LLNI_vftbl_direct(o)->arraydesc;
-
-       /* we are cloning an array */
-
-       if (ad != NULL) {
-               size = ad->dataoffset + ad->componentsize * LLNI_array_size(o);
-        
-               co = heap_alloc(size, (ad->arraytype == ARRAYTYPE_OBJECT), NULL, true);
-
-               if (co == NULL)
-                       return NULL;
-
-#if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
-               /* XXX this is only a dirty hack to make Boehm work with handles */
-
-               co = LLNI_WRAP((java_object_t *) co);
-#endif
-
-               LLNI_CRITICAL_START;
-
-               MCOPY(LLNI_DIRECT(co), LLNI_DIRECT(o), u1, size);
-
-#if defined(ENABLE_GC_CACAO)
-               heap_init_objectheader(LLNI_DIRECT(co), size);
-#endif
-
-#if defined(ENABLE_THREADS)
-               lock_init_object_lock(LLNI_DIRECT(co));
-#endif
-
-               LLNI_CRITICAL_END;
-
-               return co;
-       }
-    
-    /* we are cloning a non-array */
-
-    if (!builtin_instanceof(o, class_java_lang_Cloneable)) {
-        exceptions_throw_clonenotsupportedexception();
-        return NULL;
-    }
-
-       /* get the class of the object */
-
-       LLNI_class_get(o, c);
-
-       /* create new object */
-
-    co = builtin_new(c);
-
-    if (co == NULL)
-        return NULL;
-
-       LLNI_CRITICAL_START;
-
-       MCOPY(LLNI_DIRECT(co), LLNI_DIRECT(o), u1, c->instancesize);
-
-#if defined(ENABLE_GC_CACAO)
-       heap_init_objectheader(LLNI_DIRECT(co), c->instancesize);
-#endif
-
-#if defined(ENABLE_THREADS)
-       lock_init_object_lock(LLNI_DIRECT(co));
-#endif
-
-       LLNI_CRITICAL_END;
-
-    return co;
-}
-
-
-#if defined(ENABLE_CYCLES_STATS)
-void builtin_print_cycles_stats(FILE *file)
-{
-       fprintf(file,"builtin cylce count statistics:\n");
-
-       CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file);
-       CYCLES_STATS_PRINT(builtin_new         ,file);
-
-       fprintf(file,"\n");
-}
-#endif /* defined(ENABLE_CYCLES_STATS) */
-
-
-#if defined(ENABLE_VMLOG)
-#define NDEBUG
-#include <vmlog_cacao.c>
-#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:
- */
diff --git a/src/vm/builtin.h b/src/vm/builtin.h
deleted file mode 100644 (file)
index 8856520..0000000
+++ /dev/null
@@ -1,356 +0,0 @@
-/* src/vm/builtin.h - prototypes of builtin 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 _BUILTIN_H
-#define _BUILTIN_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* forward typedefs ***********************************************************/
-
-typedef struct builtintable_entry builtintable_entry;
-
-#include "config.h"
-#include "vm/types.h"
-
-#include "arch.h"
-#include "md-abi.h"
-
-#include "toolbox/logging.h"
-
-#include "vm/descriptor.h"
-#include "vm/utf8.h"
-
-
-/* define infinity for floating point numbers */
-
-#define FLT_NAN     0x7fc00000
-#define FLT_POSINF  0x7f800000
-#define FLT_NEGINF  0xff800000
-
-/* define infinity for double floating point numbers */
-
-#define DBL_NAN     0x7ff8000000000000LL
-#define DBL_POSINF  0x7ff0000000000000LL
-#define DBL_NEGINF  0xfff0000000000000LL
-
-
-/* float versions are not defined in GNU classpath's fdlibm */
-
-#define copysignf    copysign
-#define finitef      finite
-#define fmodf        fmod
-#define isnanf       isnan
-
-
-/* builtin functions table ****************************************************/
-
-struct builtintable_entry {
-       s4           opcode;                /* opcode which is replaced           */
-       u4           flags;                 /* e.g. check for exception           */
-       functionptr  fp;                    /* function pointer of builtin        */
-       u1          *stub;                  /* pointer to builtin stub code       */
-       char        *cclassname;            /* char name of the class             */
-       char        *cname;                 /* char name of the function          */
-       char        *cdescriptor;           /* char name of the descriptor        */
-       utf         *classname;             /* class of the function              */
-       utf         *name;                  /* name of the function               */
-       utf         *descriptor;            /* descriptor of the function         */
-       methoddesc  *md;
-};
-
-
-/* builtin table flag defines *************************************************/
-
-#define BUILTINTABLE_FLAG_STUB         0x0001 /* builtin needs a stub         */
-#define BUILTINTABLE_FLAG_EXCEPTION    0x0002 /* check for excepion on return */
-
-
-/* function prototypes ********************************************************/
-
-bool builtin_init(void);
-
-s4                                     builtintable_get_key(builtintable_entry *);
-builtintable_entry *builtintable_get_by_key(s4 key);
-builtintable_entry *builtintable_get_internal(functionptr fp);
-builtintable_entry *builtintable_get_automatic(s4 opcode);
-
-bool builtintable_replace_function(void *iptr);
-
-
-/**********************************************************************/
-/* BUILTIN FUNCTIONS                                                  */
-/**********************************************************************/
-
-/* NOTE: Builtin functions which are used in the BUILTIN* opcodes must
- * have a BUILTIN_... macro defined as seen below. In code dealing
- * with the BUILTIN* opcodes the functions may only be addressed by
- * these macros, never by their actual name! (This helps to make this
- * code more portable.)
- *
- * C and assembler code which does not deal with the BUILTIN* opcodes,
- * can use the builtin functions normally (like all other functions).
- *
- * IMPORTANT:
- * For each builtin function which is used in a BUILTIN* opcode there
- * must be an entry in the tables in vm/builtintable.inc.
- *
- * Below each prototype is either the BUILTIN_ macro definition or a
- * comment specifiying that this function is not used in BUILTIN*
- * opcodes.
- *
- * (The BUILTIN* opcodes are ICMD_BUILTIN1, ICMD_BUILTIN2 and
- * ICMD_BUILTIN3.)
- */
-
-bool builtin_instanceof(java_handle_t *obj, classinfo *c);
-/* NOT AN OP */
-bool builtin_checkcast(java_handle_t *obj, classinfo *c);
-/* NOT AN OP */
-bool builtin_arrayinstanceof(java_handle_t *h, classinfo *targetclass);
-/* NOT AN OP */
-bool builtin_fast_arrayinstanceof(java_object_t *o, classinfo *targetclass);
-#define BUILTIN_arrayinstanceof (functionptr) builtin_fast_arrayinstanceof
-bool builtin_fast_arraycheckcast(java_object_t *o, classinfo *targetclass);
-#define BUILTIN_arraycheckcast (functionptr) builtin_fast_arraycheckcast
-
-bool builtin_canstore(java_handle_objectarray_t *oa, java_handle_t *o);
-/* NOT AN OP */
-bool builtin_fast_canstore(java_objectarray_t *oa, java_object_t *o);
-#define BUILTIN_FAST_canstore (functionptr) builtin_fast_canstore
-
-void *builtin_throw_exception(java_object_t *exception);
-/* NOT AN OP */
-java_object_t *builtin_retrieve_exception(void);
-/* NOT AN OP */
-
-java_handle_t *builtin_new(classinfo *c);
-/* NOT AN OP */
-java_handle_t *builtin_java_new(java_handle_t *c);
-#define BUILTIN_new (functionptr) builtin_java_new
-
-#if defined(ENABLE_TLH)
-#define BUILTIN_tlh_new (functionptr) builtin_tlh_new
-java_handle_t *builtin_tlh_new(classinfo *c);
-#endif
-
-#if defined(ENABLE_ESCAPE_REASON)
-#define BUILTIN_escape_reason_new (functionptr)builtin_escape_reason_new
-java_handle_t *builtin_escape_reason_new(classinfo *c);
-#endif
-
-java_object_t *builtin_fast_new(classinfo *c);
-#define BUILTIN_FAST_new (functionptr) builtin_fast_new
-
-java_handle_t *builtin_newarray(int32_t size, classinfo *arrayclass);
-/* NOT AN OP */
-java_handle_t *builtin_java_newarray(int32_t size, java_handle_t *arrayclass);
-#define BUILTIN_newarray (functionptr) builtin_java_newarray
-
-java_handle_objectarray_t *builtin_anewarray(int32_t size, classinfo *componentclass);
-/* NOT AN OP */
-
-java_handle_booleanarray_t *builtin_newarray_boolean(int32_t size);
-#define BUILTIN_newarray_boolean (functionptr) builtin_newarray_boolean
-java_handle_chararray_t *builtin_newarray_char(int32_t size);
-#define BUILTIN_newarray_char (functionptr) builtin_newarray_char
-java_handle_floatarray_t *builtin_newarray_float(int32_t size);
-#define BUILTIN_newarray_float (functionptr) builtin_newarray_float
-java_handle_doublearray_t *builtin_newarray_double(int32_t size);
-#define BUILTIN_newarray_double (functionptr) builtin_newarray_double
-java_handle_bytearray_t *builtin_newarray_byte(int32_t size);
-#define BUILTIN_newarray_byte (functionptr) builtin_newarray_byte
-java_handle_shortarray_t *builtin_newarray_short(int32_t size);
-#define BUILTIN_newarray_short (functionptr) builtin_newarray_short
-java_handle_intarray_t *builtin_newarray_int(int32_t size);
-#define BUILTIN_newarray_int (functionptr) builtin_newarray_int
-java_handle_longarray_t *builtin_newarray_long(int32_t size);
-#define BUILTIN_newarray_long (functionptr) builtin_newarray_long
-
-java_handle_objectarray_t *builtin_multianewarray(int n,
-                                                                                                 java_handle_t *arrayclass,
-                                                                                                 long *dims);
-#define BUILTIN_multianewarray (functionptr) builtin_multianewarray
-
-#if defined(TRACE_ARGS_NUM)
-void builtin_verbosecall_enter(s8 a0, s8 a1,
-# if TRACE_ARGS_NUM >= 4
-                                                          s8 a2, s8 a3,
-# endif
-# if TRACE_ARGS_NUM >= 6
-                                                          s8 a4, s8 a5,
-# endif
-# if TRACE_ARGS_NUM == 8
-                                                          s8 a6, s8 a7,
-# endif
-                                                          methodinfo *m);
-/* NOT AN OP */
-#endif /* defined(TRACE_ARGS_NUM) */
-
-void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m);
-/* NOT AN OP */
-
-s4 builtin_idiv(s4 a, s4 b);
-#define BUILTIN_idiv (functionptr) builtin_idiv
-s4 builtin_irem(s4 a, s4 b);
-#define BUILTIN_irem (functionptr) builtin_irem
-
-s8 builtin_ladd(s8 a, s8 b);
-#define BUILTIN_ladd (functionptr) builtin_ladd
-s8 builtin_lsub(s8 a, s8 b);
-#define BUILTIN_lsub (functionptr) builtin_lsub
-s8 builtin_lmul(s8 a, s8 b);
-#define BUILTIN_lmul (functionptr) builtin_lmul
-
-s8 builtin_ldiv(s8 a, s8 b);
-#define BUILTIN_ldiv (functionptr) builtin_ldiv
-s8 builtin_lrem(s8 a, s8 b);
-#define BUILTIN_lrem (functionptr) builtin_lrem
-
-s8 builtin_lshl(s8 a, s4 b);
-#define BUILTIN_lshl (functionptr) builtin_lshl
-s8 builtin_lshr(s8 a, s4 b);
-#define BUILTIN_lshr (functionptr) builtin_lshr
-s8 builtin_lushr(s8 a, s4 b);
-#define BUILTIN_lushr (functionptr) builtin_lushr
-s8 builtin_land(s8 a, s8 b);
-#define BUILTIN_land (functionptr) builtin_land
-s8 builtin_lor(s8 a, s8 b);
-#define BUILTIN_lor (functionptr) builtin_lor
-s8 builtin_lxor(s8 a, s8 b);
-#define BUILTIN_lxor (functionptr) builtin_lxor
-s8 builtin_lneg(s8 a);
-#define BUILTIN_lneg (functionptr) builtin_lneg
-s4 builtin_lcmp(s8 a, s8 b);
-#define BUILTIN_lcmp (functionptr) builtin_lcmp
-
-float builtin_fadd(float a, float b);
-#define BUILTIN_fadd (functionptr) builtin_fadd
-float builtin_fsub(float a, float b);
-#define BUILTIN_fsub (functionptr) builtin_fsub
-float builtin_fmul(float a, float b);
-#define BUILTIN_fmul (functionptr) builtin_fmul
-float builtin_fdiv(float a, float b);
-#define BUILTIN_fdiv (functionptr) builtin_fdiv
-float builtin_fneg(float a);         
-#define BUILTIN_fneg (functionptr) builtin_fneg
-s4 builtin_fcmpl(float a, float b);  
-#define BUILTIN_fcmpl (functionptr) builtin_fcmpl
-s4 builtin_fcmpg(float a, float b);  
-#define BUILTIN_fcmpg (functionptr) builtin_fcmpg
-float builtin_frem(float a, float b);
-#define BUILTIN_frem (functionptr) builtin_frem
-
-double builtin_dadd(double a, double b);
-#define BUILTIN_dadd (functionptr) builtin_dadd
-double builtin_dsub(double a, double b);
-#define BUILTIN_dsub (functionptr) builtin_dsub
-double builtin_dmul(double a, double b);
-#define BUILTIN_dmul (functionptr) builtin_dmul
-double builtin_ddiv(double a, double b);
-#define BUILTIN_ddiv (functionptr) builtin_ddiv
-double builtin_dneg(double a);          
-#define BUILTIN_dneg (functionptr) builtin_dneg
-s4 builtin_dcmpl(double a, double b);   
-#define BUILTIN_dcmpl (functionptr) builtin_dcmpl
-s4 builtin_dcmpg(double a, double b);   
-#define BUILTIN_dcmpg (functionptr) builtin_dcmpg
-double builtin_drem(double a, double b);
-#define BUILTIN_drem (functionptr) builtin_drem
-
-s8       builtin_i2l(s4 i);
-/* NOT AN OP */
-float    builtin_i2f(s4 i);
-#define BUILTIN_i2f (functionptr) builtin_i2f
-double   builtin_i2d(s4 i);
-#define BUILTIN_i2d (functionptr) builtin_i2d
-s4       builtin_l2i(s8 l);
-/* NOT AN OP */
-float    builtin_l2f(s8 l);
-#define BUILTIN_l2f (functionptr) builtin_l2f
-double   builtin_l2d(s8 l);
-#define BUILTIN_l2d (functionptr) builtin_l2d
-
-s4       builtin_f2i(float a);
-#define BUILTIN_f2i (functionptr) builtin_f2i
-s4       asm_builtin_f2i(float a);
-/* NOT AN OP */
-s8       builtin_f2l(float a);
-#define BUILTIN_f2l (functionptr) builtin_f2l
-s8       asm_builtin_f2l(float a);
-/* NOT AN OP */
-
-double   builtin_f2d(float a);
-#define BUILTIN_f2d (functionptr) builtin_f2d
-
-s4       builtin_d2i(double a);
-#define BUILTIN_d2i (functionptr) builtin_d2i
-s4       asm_builtin_d2i(double a);
-/* NOT AN OP */
-s8       builtin_d2l(double a);
-#define BUILTIN_d2l (functionptr) builtin_d2l
-s8       asm_builtin_d2l(double a);
-/* NOT AN OP */
-
-float    builtin_d2f(double a);
-#define BUILTIN_d2f (functionptr) builtin_d2f
-
-java_handle_t *builtin_clone(void *env, java_handle_t *o);
-#define BUILTIN_clone (functionptr) builtin_clone
-
-void builtin_arraycopy(java_handle_t *src, s4 srcStart,
-                                          java_handle_t *dest, s4 destStart, s4 len);
-#define BUILTIN_arraycopy (functionptr) builtin_arraycopy
-
-s8 builtin_nanotime(void);
-s8 builtin_currenttimemillis(void);
-#define BUILTIN_currenttimemillis (functionptr) builtin_currenttimemillis
-
-#if defined(ENABLE_CYCLES_STATS)
-void builtin_print_cycles_stats(FILE *file);
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _BUILTIN_H */
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
diff --git a/src/vm/builtintable.inc b/src/vm/builtintable.inc
deleted file mode 100644 (file)
index 3f5781f..0000000
+++ /dev/null
@@ -1,1109 +0,0 @@
-/* src/vm/builtintable.inc - tables of builtin 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 "arch.h"
-
-#include "threads/lock-common.h"
-
-#include "vm/builtin.h"
-
-#include "vm/jit/jit.h"
-
-
-/* internal and not automatically replaced functions **************************/
-
-static builtintable_entry builtintable_internal[] = {
-
-#if defined(__ALPHA__) || defined(DISABLE_GC)
-       {
-               ICMD_F2L,
-               0,
-               BUILTIN_f2l,
-               NULL,
-               NULL,
-               "f2l",
-               "(F)J",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-       {
-               ICMD_D2L,
-               0,
-               BUILTIN_d2l,
-               NULL,
-               NULL,
-               "d2l",
-               "(D)J",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-       {
-               ICMD_F2I,
-               0,
-               BUILTIN_f2i,
-               NULL,
-               NULL,
-               "f2i",
-               "(F)I",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-       {
-               ICMD_D2I,
-               0,
-               BUILTIN_d2i,
-               NULL,
-               NULL,
-               "d2i",
-               "(D)I",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-#endif
-
-#if !SUPPORT_DIVISION || defined(DISABLE_GC)
-       {
-               ICMD_IDIV,
-               0,
-               BUILTIN_idiv,
-               NULL,
-               NULL,
-               "idiv",
-               "(II)I",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-       {
-               ICMD_IREM,
-               0,
-               BUILTIN_irem,
-               NULL,
-               NULL,
-               "irem",
-               "(II)I",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-#endif
-
-#if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) || defined(DISABLE_GC)
-       {
-               ICMD_LDIV,
-               0,
-               BUILTIN_ldiv,
-               NULL,
-               NULL,
-               "ldiv",
-               "(JJ)J",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-       {
-               ICMD_LREM,
-               0,
-               BUILTIN_lrem,
-               NULL,
-               NULL,
-               "lrem",
-               "(JJ)J",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-#endif
-
-       {
-               ICMD_FREM,
-               0,
-               BUILTIN_frem,
-               NULL,
-               NULL,
-               "frem",
-               "(FF)F",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-       {
-               ICMD_DREM,
-               0,
-               BUILTIN_drem,
-               NULL,
-               NULL,
-               "drem",
-               "(DD)D",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-
-
-       /* internal functions *****************************************************/
-
-       {
-               ICMD_NEW,
-               BUILTINTABLE_FLAG_STUB,
-               BUILTIN_new,
-               NULL,
-               NULL,
-               "new",
-               "(Ljava/lang/Class;)Ljava/lang/Object;",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-
-#if defined(ENABLE_TLH)
-       {
-               ICMD_NEW,
-               BUILTINTABLE_FLAG_STUB,
-               BUILTIN_tlh_new,
-               NULL,
-               NULL,
-               "tlh_new",
-               "(Ljava/lang/Class;)Ljava/lang/Object;",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-#endif
-
-#if defined(ENABLE_ESCAPE_REASON)
-       {
-               ICMD_NEW,
-               BUILTINTABLE_FLAG_STUB,
-               BUILTIN_escape_reason_new,
-               NULL,
-               NULL,
-               "escape_reason_new",
-               "(Ljava/lang/Class;)Ljava/lang/Object;",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-#endif
-
-       {
-               ICMD_NEW,
-               0,
-               BUILTIN_FAST_new,
-               NULL,
-               NULL,
-               "fast-new",
-               "(Ljava/lang/Class;)Ljava/lang/Object;",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-       {
-               ICMD_ANEWARRAY,
-               BUILTINTABLE_FLAG_STUB,
-               BUILTIN_newarray,
-               NULL,
-               NULL,
-               "newarray",
-               "(ILjava/lang/Class;)[Ljava/lang/Object;",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-       {
-               ICMD_NEWARRAY,
-               BUILTINTABLE_FLAG_STUB,
-               BUILTIN_newarray_boolean,
-               NULL,
-               NULL,
-               "newarray_boolean",
-               "(I)[Z",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-       {
-               ICMD_NEWARRAY,
-               BUILTINTABLE_FLAG_STUB,
-               BUILTIN_newarray_byte,
-               NULL,
-               NULL,
-               "newarray_byte",
-               "(I)[B",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-       {
-               ICMD_NEWARRAY,
-               BUILTINTABLE_FLAG_STUB,
-               BUILTIN_newarray_char,
-               NULL,
-               NULL,
-               "newarray_char",
-               "(I)[C",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-       {
-               ICMD_NEWARRAY,
-               BUILTINTABLE_FLAG_STUB,
-               BUILTIN_newarray_short,
-               NULL,
-               NULL,
-               "newarray_short",
-               "(I)[S",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-       {
-               ICMD_NEWARRAY,
-               BUILTINTABLE_FLAG_STUB,
-               BUILTIN_newarray_int,
-               NULL,
-               NULL,
-               "newarray_int",
-               "(I)[I",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-       {
-               ICMD_NEWARRAY,
-               BUILTINTABLE_FLAG_STUB,
-               BUILTIN_newarray_long,
-               NULL,
-               NULL,
-               "newarray_long",
-               "(I)[J",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-       {
-               ICMD_NEWARRAY,
-               BUILTINTABLE_FLAG_STUB,
-               BUILTIN_newarray_float,
-               NULL,
-               NULL,
-               "newarray_float",
-               "(I)[F",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-       {
-               ICMD_NEWARRAY,
-               BUILTINTABLE_FLAG_STUB,
-               BUILTIN_newarray_double,
-               NULL,
-               NULL,
-               "newarray_double",
-               "(I)[D",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-       {
-               ICMD_MULTIANEWARRAY,
-               BUILTINTABLE_FLAG_STUB,
-               BUILTIN_multianewarray,
-               NULL,
-               NULL,
-               "multianewarray",
-               /* XXX it should be: "(ILjava/lang/Class;[I)[Ljava/lang/Object;", */
-               "(ILjava/lang/Class;I)[Ljava/lang/Object;",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-       {
-               ICMD_CHECKCAST,
-               0,
-               BUILTIN_arraycheckcast,
-               NULL,
-               NULL,
-               "arraycheckcast",
-               "([Ljava/lang/Object;[Ljava/lang/Object;)[Ljava/lang/Object;",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-       {
-               ICMD_INSTANCEOF,
-               0,
-               BUILTIN_arrayinstanceof,
-               NULL,
-               NULL,
-               "arrayinstanceof",
-               "([Ljava/lang/Object;[Ljava/lang/Object;)I",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-       {
-               ICMD_AASTORE,
-               0,
-               BUILTIN_FAST_canstore,
-               NULL,
-               NULL,
-               "fast-canstore",
-               "([Ljava/lang/Object;Ljava/lang/Object;)I",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-
-#if defined(ENABLE_THREADS)
-       {
-               ICMD_MONITORENTER,
-               BUILTINTABLE_FLAG_STUB,
-               LOCK_monitor_enter,
-               NULL,
-               NULL,
-               "monitorenter",
-               "(Ljava/lang/Object;)V",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-       {
-               ICMD_MONITOREXIT,
-               BUILTINTABLE_FLAG_STUB,
-               LOCK_monitor_exit,
-               NULL,
-               NULL,
-               "monitorexit",
-               "(Ljava/lang/Object;)V",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-#endif
-
-
-       /* stop entry */
-
-       {
-               255,
-               0,
-               NULL,
-               NULL,
-               NULL,
-               NULL,
-               NULL,
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-};
-
-
-/* automatically replaced functions *******************************************/
-
-static builtintable_entry builtintable_automatic[] = {
-
-#if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
-       {
-               ICMD_LCMP,
-               0,
-               BUILTIN_lcmp,
-               NULL,
-               NULL,
-               "lcmp",
-               "(JJ)I",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-#endif
-
-#if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
-       {
-               ICMD_LAND,
-               0,
-               BUILTIN_land,
-               NULL,
-               NULL,
-               "land",
-               "(JJ)J",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-       {
-               ICMD_LOR,
-               0,
-               BUILTIN_lor,
-               NULL,
-               NULL,
-               "lor",
-               "(JJ)J",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-       {
-               ICMD_LXOR,
-               0,
-               BUILTIN_lxor,
-               NULL,
-               NULL,
-               "lxor",
-               "(JJ)J",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-#endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
-
-#if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
-       {
-               ICMD_LSHL,
-               0,
-               BUILTIN_lshl,
-               NULL,
-               NULL,
-               "lshl",
-               "(JI)J",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-       {
-               ICMD_LSHR,
-               0,
-               BUILTIN_lshr,
-               NULL,
-               NULL,
-               "lshr",
-               "(JI)J",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-       {
-               ICMD_LUSHR,
-               0,
-               BUILTIN_lushr,
-               NULL,
-               NULL,
-               "lushr",
-               "(JI)J",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-#endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
-
-#if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
-       {
-               ICMD_LADD,
-               0,
-               BUILTIN_ladd,
-               NULL,
-               NULL,
-               "ladd",
-               "(JJ)J",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-       {
-               ICMD_LSUB,
-               0,
-               BUILTIN_lsub,
-               NULL,
-               NULL,
-               "lsub",
-               "(JJ)J",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-       {
-               ICMD_LNEG,
-               0,
-               BUILTIN_lneg,
-               NULL,
-               NULL,
-               "lneg",
-               "(J)J",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-#endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
-
-#if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
-       {
-               ICMD_LMUL,
-               0,
-               BUILTIN_lmul,
-               NULL,
-               NULL,
-               "lmul",
-               "(JJ)J",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-#endif
-
-#if !(SUPPORT_FLOAT && SUPPORT_I2F)
-       {
-               ICMD_I2F,
-               0,
-               BUILTIN_i2f,
-               NULL,
-               NULL,
-               "i2f",
-               "(I)F",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-#endif
-
-#if !(SUPPORT_DOUBLE && SUPPORT_I2D)
-       {
-               ICMD_I2D,
-               0,
-               BUILTIN_i2d,
-               NULL,
-               NULL,
-               "i2d",
-               "(I)D",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-#endif
-
-#if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
-       {
-               ICMD_L2F,
-               0,
-               BUILTIN_l2f,
-               NULL,
-               NULL,
-               "l2f",
-               "(J)F",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-#endif
-
-#if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
-       {
-               ICMD_L2D,
-               0,
-               BUILTIN_l2d,
-               NULL,
-               NULL,
-               "l2d",
-               "(J)D",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-#endif
-
-#if !(SUPPORT_FLOAT && SUPPORT_F2I)
-       {
-               ICMD_F2I,
-               0,
-               BUILTIN_f2i,
-               NULL,
-               NULL,
-               "f2i",
-               "(F)I",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-#endif
-
-#if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L)
-       {
-               ICMD_F2L,
-               0,
-               BUILTIN_f2l,
-               NULL,
-               NULL,
-               "f2l",
-               "(F)J",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-#endif
-
-#if !(SUPPORT_DOUBLE && SUPPORT_D2I)
-       {
-               ICMD_D2I,
-               0,
-               BUILTIN_d2i,
-               NULL,
-               NULL,
-               "d2i",
-               "(D)I",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-#endif
-
-#if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L)
-       {
-               ICMD_D2L,
-               0,
-               BUILTIN_d2l,
-               NULL,
-               NULL,
-               "d2l",
-               "(D)J",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-#endif
-
-
-       /* float functions ********************************************************/
-
-#if !SUPPORT_FLOAT
-       {
-               ICMD_FADD,
-               0,
-               BUILTIN_fadd,
-               NULL,
-               NULL,
-               "fadd",
-               "(FF)F",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-       {
-               ICMD_FSUB,
-               0,
-               BUILTIN_fsub,
-               NULL,
-               NULL,
-               "fsub",
-               "(FF)F",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-       {
-               ICMD_FMUL,
-               0,
-               BUILTIN_fmul,
-               NULL,
-               NULL,
-               "fmul",
-               "(FF)F",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-       {
-               ICMD_FDIV,
-               0,
-               BUILTIN_fdiv,
-               NULL,
-               NULL,
-               "fdiv",
-               "(FF)F",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-       {
-               ICMD_FNEG,
-               0,
-               BUILTIN_fneg,
-               NULL,
-               NULL,
-               "fneg",
-               "(F)F",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-#endif /* !SUPPORT_FLOAT */
-
-#if !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP
-       {
-               ICMD_FCMPL,
-               0,
-               BUILTIN_fcmpl,
-               NULL,
-               NULL,
-               "fcmpl",
-               "(FF)I",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-       {
-               ICMD_FCMPG,
-               0,
-               BUILTIN_fcmpg,
-               NULL,
-               NULL,
-               "fcmpg",
-               "(FF)I",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-#endif /* !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP */
-
-
-       /* double functions *******************************************************/
-
-#if !SUPPORT_DOUBLE
-       {
-               ICMD_DADD,
-               0,
-               BUILTIN_dadd,
-               NULL,
-               NULL,
-               "dadd",
-               "(DD)D",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-       {
-               ICMD_DSUB,
-               0,
-               BUILTIN_dsub,
-               NULL,
-               NULL,
-               "dsub",
-               "(DD)D",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-       {
-               ICMD_DMUL,
-               0,
-               BUILTIN_dmul,
-               NULL,
-               NULL,
-               "dmul",
-               "(DD)D",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-       {
-               ICMD_DDIV,
-               0,
-               BUILTIN_ddiv,
-               NULL,
-               NULL,
-               "ddiv",
-               "(DD)D",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-       {
-               ICMD_DNEG,
-               0,
-               BUILTIN_dneg,
-               NULL,
-               NULL,
-               "dneg",
-               "(D)D",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-#endif /* !SUPPORT_DOUBLE */
-
-#if !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP
-       {
-               ICMD_DCMPL,
-               0,
-               BUILTIN_dcmpl,
-               NULL,
-               NULL,
-               "dcmpl",
-               "(DD)I",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-       {
-               ICMD_DCMPG,
-               0,
-               BUILTIN_dcmpg,
-               NULL,
-               NULL,
-               "dcmpg",
-               "(DD)I",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-#endif /* !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP */
-
-
-       /* float/double functions *************************************************/
-
-#if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
-       {
-               ICMD_F2D,
-               0,
-               BUILTIN_f2d,
-               NULL,
-               NULL,
-               "f2d",
-               "(F)D",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-       {
-               ICMD_D2F,
-               0,
-               BUILTIN_d2f,
-               NULL,
-               NULL,
-               "d2f",
-               "(D)F",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-#endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
-
-
-       /* prevent a compiler warning if everything is supported (e.g. i386) */
-
-       {
-               255,
-               0,
-               NULL,
-               NULL,
-               NULL,
-               NULL,
-               NULL,
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-};
-
-
-/* automatically replaced functions *******************************************/
-
-static builtintable_entry builtintable_function[] = {
-#if defined(ENABLE_JIT)
-
-       /* java.lang.VMSystem.arraycopy(Ljava/lang/Object;ILjava/lang/Object;II)V STATIC NATIVE */
-
-       {
-               ICMD_BUILTIN,
-               BUILTINTABLE_FLAG_STUB | BUILTINTABLE_FLAG_EXCEPTION,
-               BUILTIN_arraycopy,
-               NULL,
-               "java/lang/VMSystem",
-               "arraycopy",
-               "(Ljava/lang/Object;ILjava/lang/Object;II)V",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-
-       /* java.lang.System.arraycopy(Ljava/lang/Object;ILjava/lang/Object;II)V PUBLIC STATIC */
-
-#if 0
-       /* We disable this one until we have a fix for the stacktrace
-          issue. */
-
-       {
-               ICMD_BUILTIN,
-               BUILTINTABLE_FLAG_STUB | BUILTINTABLE_FLAG_EXCEPTION,
-               BUILTIN_arraycopy,
-               NULL,
-               "java/lang/System",
-               "arraycopy",
-               "(Ljava/lang/Object;ILjava/lang/Object;II)V",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-#endif
-
-       /* java.lang.VMSystem.currentTimeMillis()J PUBLIC STATIC */
-
-       {
-               ICMD_BUILTIN,
-               0,
-               BUILTIN_currenttimemillis,
-               NULL,
-               "java/lang/VMSystem",
-               "currentTimeMillis",
-               "()J",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-
-       /* java.lang.System.currentTimeMillis()J PUBLIC STATIC */
-
-       {
-               ICMD_BUILTIN,
-               0,
-               BUILTIN_currenttimemillis,
-               NULL,
-               "java/lang/System",
-               "currentTimeMillis",
-               "()J",
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-
-#endif /* defined(ENABLE_JIT) */
-
-       /* stop entry */
-
-       {
-               255,
-               0,
-               NULL,
-               NULL,
-               NULL,
-               NULL,
-               NULL,
-               NULL,
-               NULL,
-               NULL,
-               NULL
-       },
-};
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
index a775a758a6ba884c1e135bb8c2bfbbe7f57de671..1fa771c7b2e013a8689ed1cd64d01a152825736b 100644 (file)
 
 #include "native/llni.h"
 
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
+#include "threads/mutex.hpp"
 
 #include "toolbox/logging.h"
 
-#include "vm/array.h"
-#include "vm/builtin.h"
+#include "vm/array.hpp"
+#include "vm/jit/builtin.hpp"
 #include "vm/class.h"
 #include "vm/classcache.h"
 #include "vm/exceptions.hpp"
@@ -52,7 +53,7 @@
 #include "vm/javaobjects.hpp"
 #include "vm/jit/jitcache.hpp"
 #include "vm/linker.h"
-#include "vm/loader.h"
+#include "vm/loader.hpp"
 #include "vm/options.h"
 #include "vm/resolve.h"
 
@@ -60,7 +61,7 @@
 # include "vm/statistics.h"
 #endif
 
-#include "vm/suck.h"
+#include "vm/suck.hpp"
 #include "vm/utf8.h"
 
 #include "vm/jit/asmpart.h"
@@ -180,7 +181,7 @@ classinfo *class_create_classinfo(utf *classname)
     c->cache_file_fd = 0;
 #endif
 
-       LOCK_INIT_OBJECT_LOCK(&c->object.header);
+       Lockword_init(&(c->object.header.lockword));
 
        return c;
 }
@@ -827,25 +828,22 @@ classinfo *class_array_of(classinfo *component, bool link)
     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 = MNEW(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 = MNEW(char, namelen + 3);
         namebuf[0] = '[';
         namebuf[1] = 'L';
         MCOPY(namebuf + 2, component->name->text, char, namelen);
@@ -855,9 +853,9 @@ classinfo *class_array_of(classinfo *component, bool link)
 
        u = utf_new(namebuf, namelen);
 
-       c = get_array_class(u, cl, cl, link);
+       MFREE(namebuf, char, namelen);
 
-       DRELEASE;
+       c = get_array_class(u, cl, cl, link);
 
        return c;
 }
@@ -875,9 +873,6 @@ 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");
@@ -889,13 +884,13 @@ classinfo *class_multiarray_of(s4 dim, classinfo *element, bool link)
     
     if (element->name->text[0] == '[') {
         /* the element is itself an array */
-        namebuf = DMNEW(char, namelen + dim);
+        namebuf = MNEW(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 = MNEW(char, namelen + 2 + dim);
         namebuf[dim] = 'L';
         memcpy(namebuf + dim + 1, element->name->text, namelen);
         namelen += (2 + dim);
@@ -903,13 +898,15 @@ classinfo *class_multiarray_of(s4 dim, classinfo *element, bool link)
     }
        memset(namebuf, '[', dim);
 
-       c = get_array_class(utf_new(namebuf, namelen),
+       utf* u = utf_new(namebuf, namelen);
+
+       MFREE(namebuf, char, namelen);
+
+       c = get_array_class(u,
                                                element->classloader,
                                                element->classloader,
                                                link);
 
-       DRELEASE;
-
        return c;
 }
 
@@ -1037,25 +1034,22 @@ constant_classref *class_get_classref_multiarray_of(s4 dim, constant_classref *r
     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);
+        namebuf = MNEW(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 = MNEW(char, namelen + 2 + dim);
         namebuf[dim] = 'L';
         memcpy(namebuf + dim + 1, ref->name->text, namelen);
         namelen += (2 + dim);
@@ -1063,9 +1057,11 @@ constant_classref *class_get_classref_multiarray_of(s4 dim, constant_classref *r
     }
        memset(namebuf, '[', dim);
 
-    cr = class_get_classref(ref->referer,utf_new(namebuf, namelen));
+       utf* u = utf_new(namebuf, namelen);
+
+       MFREE(namebuf, char, namelen);
 
-       DRELEASE;
+    cr = class_get_classref(ref->referer, u);
 
        return cr;
 }
@@ -1484,12 +1480,12 @@ bool class_isanysubclass(classinfo *sub, classinfo *super)
                if (sub->flags & ACC_INTERFACE)
                        return (super == class_java_lang_Object);
 
-               LOCK_MONITOR_ENTER(linker_classrenumber_lock);
+               Mutex_lock(linker_classrenumber_mutex);
 
                diffval = sub->vftbl->baseval - super->vftbl->baseval;
                result  = diffval <= (uint32_t) super->vftbl->diffval;
 
-               LOCK_MONITOR_EXIT(linker_classrenumber_lock);
+               Mutex_unlock(linker_classrenumber_mutex);
        }
 
        return result;
@@ -2375,15 +2371,7 @@ void class_showconstantpool (classinfo *c)
                                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 
-                               }
+                               printf ("Long -> %ld", (long int) ((constant_long*)e) -> value);
                                break;
                        case CONSTANT_NameAndType:
                                {
index a1434be849b3a4cf698d44c9d83478d375f61030..f257dd8b3b9e5108b64dd757eac6ca10235724a5 100644 (file)
 #ifndef _CLASS_H
 #define _CLASS_H
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /* forward typedefs ***********************************************************/
 
 typedef struct classinfo      classinfo; 
@@ -43,16 +39,14 @@ typedef struct extra_classref extra_classref;
 
 #include "vm/types.h"
 
-#include "toolbox/list.h"
-
 #if defined(ENABLE_JAVASE)
 # include "vm/annotation.h"
 #endif
 
-#include "vm/field.h"
+#include "vm/field.hpp"
 #include "vm/global.h"
 #include "vm/linker.h"
-#include "vm/loader.h"
+#include "vm/loader.hpp"
 #include "vm/method.h"
 #include "vm/references.h"
 #include "vm/string.hpp"
@@ -197,6 +191,10 @@ struct extra_classref {
 
 /* inline functions ***********************************************************/
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /**
  * Returns the classname of the class, where slashes ('/') are
  * replaced by dots ('.').
index 3de9665c1527ab2e7c093949c2bb60ec43d5d795..6324f2a78787e0c012d30eab9b0109a0109481ca 100644 (file)
@@ -31,7 +31,8 @@
 
 #include "mm/memory.h"
 
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
+#include "threads/mutex.hpp"
 
 #include "toolbox/hashtable.h"
 #include "toolbox/logging.h"
@@ -209,8 +210,8 @@ void classcache_print_statistics(FILE *file) {
        /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
 
 #if defined(ENABLE_THREADS)
-# define CLASSCACHE_LOCK()      LOCK_MONITOR_ENTER(lock_hashtable_classcache)
-# define CLASSCACHE_UNLOCK()    LOCK_MONITOR_EXIT(lock_hashtable_classcache)
+# define CLASSCACHE_LOCK()      Mutex_lock(classcache_hashtable_mutex)
+# define CLASSCACHE_UNLOCK()    Mutex_unlock(classcache_hashtable_mutex)
 #else
 # define CLASSCACHE_LOCK()
 # define CLASSCACHE_UNLOCK()
@@ -223,7 +224,7 @@ void classcache_print_statistics(FILE *file) {
 hashtable hashtable_classcache;
 
 #if defined(ENABLE_THREADS)
-static java_object_t *lock_hashtable_classcache;
+static Mutex *classcache_hashtable_mutex;
 #endif
 
 
@@ -258,11 +259,9 @@ bool classcache_init(void)
        hashtable_create(&hashtable_classcache, CLASSCACHE_INIT_SIZE);
 
 #if defined(ENABLE_THREADS)
-       /* create utf hashtable lock object */
+       /* create utf hashtable mutex */
 
-       lock_hashtable_classcache = NEW(java_object_t);
-
-       LOCK_INIT_OBJECT_LOCK(lock_hashtable_classcache);
+       classcache_hashtable_mutex = Mutex_new();
 #endif
 
        /* everything's ok */
index e8286e050d066a1de38dc5112c08d6c08f47a813..44ac5d80a626e9504aaa1a0c50f214e7502643a6 100644 (file)
 
 #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/loader.hpp"
 #include "vm/references.h"
 
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /* forward declarations *******************************************************/
 
 typedef struct classcache_name_entry classcache_name_entry;
index 1f104a0f770574452bd2ec52756b6d3d803055e4..87fb9c7febcc16253747658c437dc3ba98920253 100644 (file)
@@ -151,6 +151,10 @@ struct methoddesc {
 
 /* function prototypes ********************************************************/
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 descriptor_pool * descriptor_pool_new(classinfo *referer);
 
 bool descriptor_pool_add_class(descriptor_pool *pool,utf *name);
@@ -182,6 +186,10 @@ void descriptor_debug_print_paramdesc(FILE *file,paramdesc *d);
 void descriptor_pool_debug_dump(descriptor_pool *pool, FILE *file);
 #endif /* !defined(NDEBUG) */
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* _DESCRIPTOR_H */
 
 
index e97c6e1ffcead23e89222369de6b6a6956cead0b..eb57f9e6c16e15700d2a83e75787f1b5ba2e08da 100644 (file)
 
 #include "mm/memory.h"
 
-#include "native/jni.h"
 #include "native/llni.h"
-#include "native/native.h"
+#include "native/native.hpp"
 
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
 #include "threads/thread.hpp"
 
 #include "toolbox/util.h"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #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/loader.hpp"
 #include "vm/method.h"
 #include "vm/options.h"
 #include "vm/os.hpp"
 #include "vm/vm.hpp"
 
 #include "vm/jit/asmpart.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
 #include "vm/jit/methodheader.h"
-#include "vm/jit/patcher-common.h"
-#include "vm/jit/show.h"
+#include "vm/jit/patcher-common.hpp"
+#include "vm/jit/show.hpp"
 #include "vm/jit/stacktrace.hpp"
 #include "vm/jit/trace.hpp"
 
@@ -242,7 +241,7 @@ static void exceptions_abort(utf *classname, utf *message)
 
        log_finish();
 
-       vm_abort("Aborting...");
+       os::abort("Aborting...");
 }
 
 
@@ -267,7 +266,7 @@ static java_handle_t *exceptions_new_class_utf(classinfo *c, utf *message)
        java_handle_t *s;
        java_handle_t *o;
 
-       if (vm->is_initializing()) {
+       if (VM::get_current()->is_initializing()) {
                /* This can happen when global class variables are used which
                   are not initialized yet. */
 
@@ -305,7 +304,7 @@ static java_handle_t *exceptions_new_utf(utf *classname)
        classinfo     *c;
        java_handle_t *o;
 
-       if (vm->is_initializing())
+       if (VM::get_current()->is_initializing())
                exceptions_abort(classname, NULL);
 
        c = load_class_bootstrap(classname);
@@ -343,7 +342,7 @@ static java_handle_t *exceptions_new_utf_javastring(utf *classname,
        java_handle_t *o;
        classinfo     *c;
    
-       if (vm->is_initializing())
+       if (VM::get_current()->is_initializing())
                exceptions_abort(classname, NULL);
 
        c = load_class_bootstrap(classname);
@@ -380,7 +379,7 @@ static java_handle_t *exceptions_new_utf_utf(utf *classname, utf *message)
        classinfo     *c;
        java_handle_t *o;
 
-       if (vm->is_initializing())
+       if (VM::get_current()->is_initializing())
                exceptions_abort(classname, message);
 
        c = load_class_bootstrap(classname);
@@ -455,7 +454,7 @@ static void exceptions_throw_utf_throwable(utf *classname,
        classinfo           *c;
        methodinfo          *m;
 
-       if (vm->is_initializing())
+       if (VM::get_current()->is_initializing())
                exceptions_abort(classname, NULL);
 
        java_lang_Throwable jlt(cause);
@@ -507,7 +506,7 @@ static void exceptions_throw_utf_exception(utf *classname,
        java_handle_t *o;
        methodinfo    *m;
 
-       if (vm->is_initializing())
+       if (VM::get_current()->is_initializing())
                exceptions_abort(classname, NULL);
 
        c = load_class_bootstrap(classname);
@@ -552,7 +551,7 @@ static void exceptions_throw_utf_exception(utf *classname,
 
 static void exceptions_throw_utf_cause(utf *classname, java_handle_t *cause)
 {
-       if (vm->is_initializing())
+       if (VM::get_current()->is_initializing())
                exceptions_abort(classname, NULL);
 
        java_lang_Throwable jltcause(cause);
@@ -2012,7 +2011,7 @@ void exceptions_print_stacktrace(void)
                                                                         false);
 
                if (m == NULL)
-                       vm_abort("exceptions_print_stacktrace: printStackTrace()V not found");
+                       os::abort("exceptions_print_stacktrace: printStackTrace()V not found");
 
                /* Print message. */
 
index 355c98634dc2de31d1023816e742a0b69df1fbef..924679b7d96d049f3a32945ef869e600b89335fa 100644 (file)
 #ifndef _EXCEPTIONS_HPP
 #define _EXCEPTIONS_HPP
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #include "config.h"
 #include "vm/types.h"
 
@@ -40,6 +36,10 @@ extern "C" {
 
 /* function prototypes ********************************************************/
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 java_handle_t *exceptions_get_exception(void);
 void           exceptions_set_exception(java_handle_t *o);
 void           exceptions_clear_exception(void);
diff --git a/src/vm/field.c b/src/vm/field.c
deleted file mode 100644 (file)
index a304f31..0000000
+++ /dev/null
@@ -1,561 +0,0 @@
-/* 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:
- */
diff --git a/src/vm/field.cpp b/src/vm/field.cpp
new file mode 100644 (file)
index 0000000..2cd114f
--- /dev/null
@@ -0,0 +1,561 @@
+/* src/vm/field.cpp - 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.hpp"
+#include "vm/jit/builtin.hpp"
+#include "vm/class.h"
+#include "vm/descriptor.h"
+#include "vm/exceptions.hpp"
+#include "vm/field.hpp"
+#include "vm/global.h"
+#include "vm/loader.hpp"
+#include "vm/options.h"
+#include "vm/primitive.hpp"
+#include "vm/references.h"
+#include "vm/string.hpp"
+#include "vm/suck.hpp"
+#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 = (utf*) class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
+               return false;
+
+       f->name = u;
+
+       /* Get descriptor. */
+
+       if (!(u = (utf*) 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 = (utf*) 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 = (constant_integer*) class_getconstant(c, pindex, CONSTANT_Integer)))
+                                       return false;
+
+                               f->value->i = ci->value;
+                       }
+                       break;
+
+                       case TYPE_LNG: {
+                               constant_long *cl; 
+
+                               if (!(cl = (constant_long*) class_getconstant(c, pindex, CONSTANT_Long)))
+                                       return false;
+
+                               f->value->l = cl->value;
+                       }
+                       break;
+
+                       case TYPE_FLT: {
+                               constant_float *cf;
+
+                               if (!(cf = (constant_float*) class_getconstant(c, pindex, CONSTANT_Float)))
+                                       return false;
+
+                               f->value->f = cf->value;
+                       }
+                       break;
+
+                       case TYPE_DBL: {
+                               constant_double *cd;
+
+                               if (!(cd = (constant_double*) class_getconstant(c, pindex, CONSTANT_Double)))
+                                       return false;
+
+                               f->value->d = cd->value;
+                       }
+                       break;
+
+                       case TYPE_ADR:
+                               if (!(u = (utf*) 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:
+ */
diff --git a/src/vm/field.h b/src/vm/field.h
deleted file mode 100644 (file)
index a0960c0..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-/* 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:
- */
diff --git a/src/vm/field.hpp b/src/vm/field.hpp
new file mode 100644 (file)
index 0000000..52c33eb
--- /dev/null
@@ -0,0 +1,107 @@
+/* src/vm/field.hpp - 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_HPP
+#define _FIELD_HPP
+
+/* 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.hpp"
+#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 ********************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+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
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _FIELD_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:
+ */
index 270d7eb46fbc8120b0f14387f6bc047aa871abb4..ea331ec96e9c12b7a51d2298d362f8c15ba3af0e 100644 (file)
 
 #include "mm/memory.h"
 
-#include "threads/lock-common.h"
+#include "threads/condition.hpp"
+#include "threads/mutex.hpp"
 #include "threads/thread.hpp"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/exceptions.hpp"
 #include "vm/global.h"
 #include "vm/options.h"
@@ -46,7 +47,8 @@
 /* global variables ***********************************************************/
 
 #if defined(ENABLE_THREADS)
-static java_object_t *lock_thread_finalizer;
+static Mutex     *finalizer_thread_mutex;
+static Condition *finalizer_thread_cond;
 #endif
 
 
@@ -61,9 +63,8 @@ bool finalizer_init(void)
        TRACESUBSYSTEMINITIALIZATION("finalizer_init");
 
 #if defined(ENABLE_THREADS)
-       lock_thread_finalizer = NEW(java_object_t);
-
-       LOCK_INIT_OBJECT_LOCK(lock_thread_finalizer);
+       finalizer_thread_mutex = Mutex_new();
+       finalizer_thread_cond  = Condition_new();
 #endif
 
        /* everything's ok */
@@ -84,17 +85,17 @@ bool finalizer_init(void)
 static void finalizer_thread(void)
 {
        while (true) {
-               /* get the lock on the finalizer lock object, so we can call wait */
+               /* get the lock on the finalizer mutex, so we can call wait */
 
-               LOCK_MONITOR_ENTER(lock_thread_finalizer);
+               Mutex_lock(finalizer_thread_mutex);
 
-               /* wait forever on that object till we are signaled */
+               /* wait forever on that condition till we are signaled */
        
-               LOCK_WAIT_FOREVER(lock_thread_finalizer);
+               Condition_wait(finalizer_thread_cond, finalizer_thread_mutex);
 
                /* leave the lock */
 
-               LOCK_MONITOR_EXIT(lock_thread_finalizer);
+               Mutex_unlock(finalizer_thread_mutex);
 
 #if !defined(NDEBUG)
                if (opt_DebugFinalizer)
@@ -154,15 +155,15 @@ void finalizer_notify(void)
 #if defined(ENABLE_THREADS)
        /* get the lock on the finalizer lock object, so we can call wait */
 
-       LOCK_MONITOR_ENTER(lock_thread_finalizer);
+       Mutex_lock(finalizer_thread_mutex);
 
        /* signal the finalizer thread */
-       
-       LOCK_NOTIFY(lock_thread_finalizer);
+
+       Condition_signal(finalizer_thread_cond);
 
        /* leave the lock */
 
-       LOCK_MONITOR_EXIT(lock_thread_finalizer);
+       Mutex_unlock(finalizer_thread_mutex);
 #else
        /* if we don't have threads, just run the finalizers */
 
index a9ec8c8f9735521260e13f68e49252f7054c9f8c..011d9b4a03e78ed78a64e8158fceada9e0ebcc9b 100644 (file)
@@ -230,10 +230,12 @@ typedef struct java_objectarray_t java_objectarray_t;
 #define HDRFLAG_HASH_ATTACHED 0x20
 #define HDRFLAG_REFERENCING   0x40
 
+#include "threads/lockword.hpp"
+
 struct java_object_t {                 /* header for all objects              */
        struct _vftbl *vftbl;              /* pointer to virtual function table   */
 #if defined(ENABLE_THREADS)
-       uintptr_t      lockword;
+       Lockword       lockword;
 #endif
 #if defined(ENABLE_GC_CACAO)
        uintptr_t      hdrflags;           /* word containing the GC bits         */
@@ -326,6 +328,7 @@ typedef struct java_handle_t {
        java_object_t *heap_object;
 } java_handle_t;
 
+typedef struct java_handle_array_t        { java_array_t        *heap_object; } java_handle_array_t;
 typedef struct java_handle_objectarray_t  { java_objectarray_t  *heap_object; } java_handle_objectarray_t;
 typedef struct java_handle_booleanarray_t { java_booleanarray_t *heap_object; } java_handle_booleanarray_t;
 typedef struct java_handle_bytearray_t    { java_bytearray_t    *heap_object; } java_handle_bytearray_t;
@@ -337,6 +340,7 @@ typedef struct java_handle_floatarray_t   { java_floatarray_t   *heap_object; }
 typedef struct java_handle_doublearray_t  { java_doublearray_t  *heap_object; } java_handle_doublearray_t;
 #else
 typedef java_object_t       java_handle_t;
+typedef java_array_t        java_handle_array_t;
 typedef java_objectarray_t  java_handle_objectarray_t;
 typedef java_booleanarray_t java_handle_booleanarray_t;
 typedef java_bytearray_t    java_handle_bytearray_t;
index 82d9a749e72b762cbb241cc90813a143793ec0ff..4f540e3d6f8839d2a89e5be325523f51ad46f9a8 100644 (file)
 
 #include "vm/types.h"
 
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #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/loader.hpp"
 #include "vm/options.h"
 #include "vm/vm.hpp"
 
index 904063fa7089677b3a58187fb1110e72367cf0b6..cc82bdc6e9a79f7659f784438b60bc216f64b8e1 100644 (file)
@@ -29,7 +29,7 @@
 #include "native/vm/reflection.hpp"
 
 #include "vm/access.h"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/global.h"
 #include "vm/globals.hpp"
 #include "vm/initialize.h"
index 7253e44b6bc46a8204132af2d81137b40e7e1ce7..5eb1025e26d93aa4c68bf5bc73366ee9a4c293b0 100644 (file)
 
 #include "native/llni.h"
 
+#include "threads/atomic.hpp"
+
 #include "vm/class.h"
-#include "vm/field.h"
+#include "vm/field.hpp"
 #include "vm/global.h"
 #include "vm/globals.hpp"
 #include "vm/method.h"
@@ -77,93 +79,106 @@ template<class T> inline void RawFieldAccess::raw_set(void* address, const off_t
  * afterwards.
  */
 class FieldAccess : private RawFieldAccess {
-protected:
+public:
+       // Normal field accessors.
        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);
+
+       // Volatile field accessors.
+       template<class T> static inline T    get_volatile(java_handle_t* h, const off_t offset);
+       template<class T> static inline void set_volatile(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;
+       // This function is inside a critical section.
+       GCCriticalSection cs;
 
        // XXX This should be _handle->get_object();
-       o = LLNI_UNWRAP(h);
-
-       result = raw_get<T>(o, offset);
+       java_object_t* ho = LLNI_UNWRAP(h);
+       return raw_get<T>(ho, offset);
+}
 
-       // XXX Move this to a GC inline function.
-       // gc->leave_critical();
-       LLNI_CRITICAL_END;
+template<> inline java_handle_t* FieldAccess::get(java_handle_t* h, const off_t offset)
+{
+       // This function is inside a critical section.
+       GCCriticalSection cs;
 
-       return result;
+       // XXX This should be _handle->get_object();
+       java_object_t* o = LLNI_UNWRAP(h);
+       java_object_t* result = raw_get<java_object_t*>(o, offset);
+       return LLNI_WRAP(result);
 }      
 
-template<> inline java_handle_t* FieldAccess::get(java_handle_t* h, const off_t offset)
+
+template<class T> inline void FieldAccess::set(java_handle_t* h, const off_t offset, T value)
 {
-       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;
+       // This function is inside a critical section.
+       GCCriticalSection cs;
 
-       // XXX This should be _handle->get_object();
-       o = LLNI_UNWRAP(h);
+       java_object_t* ho = LLNI_UNWRAP(h);
+       raw_set(ho, offset, value);
+}
 
-       result = raw_get<java_object_t*>(o, offset);
+template<> inline void FieldAccess::set<java_handle_t*>(java_handle_t* h, const off_t offset, java_handle_t* value)
+{
+       // This function is inside a critical section.
+       GCCriticalSection cs;
 
-       hresult = LLNI_WRAP(result);
+       // XXX This should be h->get_object();
+       java_object_t* o      = LLNI_UNWRAP(h);
+       java_object_t* ovalue = LLNI_UNWRAP(value);
+       raw_set(o, offset, ovalue);
+}
 
-       // XXX Move this to a GC inline function.
-       // gc->leave_critical();
-       LLNI_CRITICAL_END;
 
-       return result;
-}      
+template<class T> inline T FieldAccess::get_volatile(java_handle_t* h, const off_t offset)
+{
+       // This function is inside a critical section.
+       GCCriticalSection cs;
 
+       // XXX This should be _handle->get_object();
+       java_object_t* ho = LLNI_UNWRAP(h);
+       return raw_get<volatile T>(ho, offset);
+}
 
-template<class T> inline void FieldAccess::set(java_handle_t* h, const off_t offset, T value)
+template<> inline java_handle_t* FieldAccess::get_volatile(java_handle_t* h, const off_t offset)
 {
-       java_object_t* o;
+       // This function is inside a critical section.
+       GCCriticalSection cs;
+
+       // XXX This should be _handle->get_object();
+       java_object_t* o = LLNI_UNWRAP(h);
+       java_object_t* result = (java_object_t*) raw_get<volatile java_object_t*>(o, offset);
+       return LLNI_WRAP(result);
+}      
 
-       // 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);
+template<class T> inline void FieldAccess::set_volatile(java_handle_t* h, const off_t offset, T value)
+{
+       // This function is inside a critical section.
+       GCCriticalSection cs;
 
-       raw_set(o, offset, value);
+       java_object_t* ho = LLNI_UNWRAP(h);
+       raw_set(ho, offset, (volatile T) value);
 
-       // XXX Move this to a GC inline function.
-       // gc->leave_critical();
-       LLNI_CRITICAL_END;
+       // Memory barrier for the Java Memory Model.
+       Atomic::memory_barrier();
 }
 
-template<> inline void FieldAccess::set<java_handle_t*>(java_handle_t* h, const off_t offset, java_handle_t* value)
+template<> inline void FieldAccess::set_volatile<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;
+       // This function is inside a critical section.
+       GCCriticalSection cs;
 
        // XXX This should be h->get_object();
-       o      = LLNI_UNWRAP(h);
-       ovalue = LLNI_UNWRAP(value);
+       java_object_t* o      = LLNI_UNWRAP(h);
+       java_object_t* ovalue = LLNI_UNWRAP(value);
+       raw_set(o, offset, (volatile java_object_t*) ovalue);
 
-       raw_set(o, offset, ovalue);
-
-       // XXX Move this to a GC inline function.
-       // gc->leave_critical();
-       LLNI_CRITICAL_END;
+       // Memory barrier for the Java Memory Model.
+       Atomic::memory_barrier();
 }
 
 
@@ -179,17 +194,16 @@ protected:
        // Handle of Java object.
        java_handle_t* _handle;
 
-protected:
+public:
        java_lang_Object() : _handle(NULL) {}
        java_lang_Object(java_handle_t* h) : _handle(h) {}
-       java_lang_Object(jobject h) : _handle((java_handle_t*) h) {}
        virtual ~java_lang_Object() {}
 
-public:
        // Getters.
-       virtual inline java_handle_t* get_handle() const { return _handle; }
-       inline vftbl_t*               get_vftbl () const;
-       inline classinfo*             get_Class () const;
+       virtual inline java_handle_t* get_handle  () const { return _handle; }
+       inline vftbl_t*               get_vftbl   () const;
+       inline classinfo*             get_Class   () const;
+       inline int32_t                get_hashcode() const;
 
        inline bool is_null    () const;
        inline bool is_non_null() const;
@@ -198,19 +212,12 @@ public:
 
 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;
+       // This function is inside a critical section.
+       GCCriticalSection cs;
 
        // 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;
+       return o->vftbl;
 }
 
 inline classinfo* java_lang_Object::get_Class() const
@@ -218,6 +225,20 @@ inline classinfo* java_lang_Object::get_Class() const
        return get_vftbl()->clazz;
 }
 
+inline int32_t java_lang_Object::get_hashcode() const
+{
+#if defined(ENABLE_GC_CACAO)
+       return heap_get_hashcode(_handle);
+#else
+       // This function is inside a critical section.
+       GCCriticalSection cs;
+
+       // XXX This should be h->get_object();
+       java_object_t* o = LLNI_UNWRAP(_handle);
+       return (int32_t) (intptr_t) o;
+#endif
+}
+
 
 inline bool java_lang_Object::is_null() const
 {
@@ -561,7 +582,6 @@ public:
 
        // 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)
@@ -569,11 +589,6 @@ 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
@@ -636,7 +651,6 @@ private:
 
 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.
@@ -650,11 +664,6 @@ public:
        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);
@@ -813,7 +822,6 @@ private:
 
 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.
@@ -826,11 +834,6 @@ public:
 };
 
 
-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);
@@ -922,16 +925,11 @@ private:
 
 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
 {
@@ -970,7 +968,6 @@ private:
 
 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.
@@ -994,11 +991,6 @@ public:
 };
 
 
-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);
@@ -1106,7 +1098,6 @@ private:
 
 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);
@@ -1124,11 +1115,6 @@ public:
 };
 
 
-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);
@@ -1202,7 +1188,6 @@ private:
 
 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.
@@ -1225,11 +1210,6 @@ public:
 };
 
 
-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);
@@ -1333,7 +1313,6 @@ private:
 
 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.
@@ -1348,11 +1327,6 @@ public:
 };
 
 
-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);
@@ -1425,7 +1399,6 @@ private:
 
 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.
@@ -1451,10 +1424,6 @@ public:
        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)
 {
@@ -1581,7 +1550,6 @@ private:
 
 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);
@@ -1599,11 +1567,6 @@ public:
 };
 
 
-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);
@@ -1718,16 +1681,11 @@ private:
 
 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
 {
@@ -1891,7 +1849,6 @@ private:
 
 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.
@@ -1905,11 +1862,6 @@ public:
        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);
@@ -2077,8 +2029,7 @@ private:
 
 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);
+       java_lang_Throwable(java_handle_t* h, java_handle_bytearray_t* backtrace);
 
        // Getters.
        inline java_handle_bytearray_t* get_backtrace    () const;
@@ -2090,14 +2041,8 @@ public:
 };
 
 
-inline java_lang_Throwable::java_lang_Throwable(jobject h) : java_lang_Object(h)
+inline java_lang_Throwable::java_lang_Throwable(java_handle_t* h, java_handle_bytearray_t* backtrace) : 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);
 }
 
@@ -2166,7 +2111,6 @@ private:
 
 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);
@@ -2192,11 +2136,6 @@ public:
 };
 
 
-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);
@@ -2336,7 +2275,6 @@ private:
 
 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.
@@ -2359,11 +2297,6 @@ public:
 };
 
 
-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);
@@ -2498,7 +2431,6 @@ private:
 
 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);
@@ -2518,11 +2450,6 @@ public:
 };
 
 
-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);
@@ -2530,13 +2457,13 @@ inline java_lang_reflect_Method::java_lang_reflect_Method(methodinfo* m)
        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_clazz,                m->clazz);
+       set(_handle, offset_slot,                 (int32_t) (m - m->clazz->methods)); // This cast is important (see PR100).
+       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_modifiers,            (int32_t) (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));
@@ -2608,7 +2535,6 @@ private:
 
 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;
@@ -2645,7 +2571,6 @@ private:
 
 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);
 
@@ -2661,11 +2586,6 @@ public:
 };
 
 
-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);
@@ -2731,7 +2651,6 @@ private:
 
 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.
@@ -2745,10 +2664,6 @@ public:
        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)
 {
@@ -2814,7 +2729,6 @@ private:
 
 public:
        java_lang_Thread(java_handle_t* h) : java_lang_Object(h) {}
-       java_lang_Thread(jobject h);
 //     java_lang_Thread(threadobject* t);
 
        // Getters.
@@ -2827,11 +2741,6 @@ public:
 };
 
 
-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));
@@ -2878,7 +2787,6 @@ private:
 
 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;
@@ -2889,12 +2797,6 @@ public:
 };
 
 
-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);
index 6b248b46610f51badd4037d14cde9d014055ff16..c8d27ba749d5334d83230a0ae1d4c9c6e27790f8 100644 (file)
@@ -103,7 +103,7 @@ REG_SOURCES = \
        reg.h
 
 REPLACE_SOURCES += \
-       replace.h
+       replace.hpp
 
 STACK_SOURCES = \
        stack.c \
@@ -124,7 +124,7 @@ endif
 
 if ENABLE_REPLACEMENT
 REPLACE_SOURCES += \
-       replace.c
+       replace.cpp
 endif
 
 if ENABLE_VERIFIER
@@ -156,42 +156,46 @@ noinst_LTLIBRARIES = \
        libjit.la
 
 libjit_la_SOURCES = \
-       argument.c \
-       argument.h \
-       code.c \
-       code.h \
-       codegen-common.c \
-       codegen-common.h \
+       argument.cpp \
+       argument.hpp \
+       builtin.cpp \
+       builtin.hpp \
+       builtintable.inc \
+       code.cpp \
+       code.hpp \
+       codegen-common.cpp \
+       codegen-common.hpp \
        disass.h \
        $(DISASS_SOURCES) \
        dseg.c \
        dseg.h \
-       emit-common.c \
-       emit-common.h \
+       emit-common.cpp \
+       emit-common.hpp \
        exceptiontable.c \
        exceptiontable.h \
        executionstate.c \
        executionstate.h \
-       icmdtable.inc \
-       jit.c \
-       jit.h \
-       linenumbertable.c \
-       linenumbertable.h \
+       jit.cpp \
+       jit.hpp \
+       linenumbertable.cpp \
+       linenumbertable.hpp \
        methodtree.c \
        methodtree.h \
        parse.c \
        parse.h \
-       patcher-common.c \
-       patcher-common.h \
+       patcher-common.cpp \
+       patcher-common.hpp \
        $(RECOMPILE_SOURCES) \
        $(REG_SOURCES) \
        $(JITCACHE_SOURCES) \
        $(REPLACE_SOURCES) \
-       show.c \
-       show.h \
+       show.cpp \
+       show.hpp \
        $(STACK_SOURCES) \
        stacktrace.cpp \
        stacktrace.hpp \
+       stubs.cpp \
+       stubs.hpp \
        trace.cpp \
        trace.hpp \
        $(TRAP_SOURCES) \
index 6a84ade40945d8609617f94385de998e6a2232d8..2bd0e8b8b3af254500c39153d4ed046741be12eb 100644 (file)
@@ -32,7 +32,7 @@
 #include "arch.h"
 
 #include "vm/jit/abi-asm.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
 #include "vm/jit/stack.h"
 
 
@@ -64,6 +64,10 @@ extern const s4    abi_registers_float_temporary[];
 
 /* function prototypes ********************************************************/
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /* machine dependent descriptor function */
 void md_param_alloc(methoddesc *md);
 void md_param_alloc_native(methoddesc *md);
@@ -71,6 +75,10 @@ void md_param_alloc_native(methoddesc *md);
 /* machine dependent return value handling function */
 void md_return_alloc(jitdata *jd, stackelement_t *stackslot);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* _ABI_H */
 
 
index d6d6acc1002aef18fa983f49d241ab026391d7c2..7ceaea22813165d80a9a2593f0337e4fe204eef9 100644 (file)
 #include "toolbox/logging.h"
 #include "toolbox/worklist.h"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/exceptions.hpp"
 #include "vm/global.h"
 #include "vm/method.h"
 #include "vm/resolve.h"
-#include "vm/jit/codegen-common.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/codegen-common.hpp"
+#include "vm/jit/jit.hpp"
 #include "vm/jit/allocator/lsra.h"
 #include "vm/jit/allocator/liveness.h"
 
index d8b122157b698e4ea4b458186e51342ca0c10e14..f984f57ff95c1ecf582a0d551578059ec202a615 100644 (file)
@@ -39,7 +39,7 @@
 
 #include "toolbox/logging.h"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/exceptions.hpp"
 #include "vm/resolve.h"
 #include "vm/options.h"
@@ -1340,9 +1340,6 @@ void lsra_alloc(jitdata *jd, int *lifet, int lifetimecount, int *mem_use)
        struct freemem *fmem;
        struct stackslot *n;
        int lt_index;
-#ifdef HAS_4BYTE_STACKSLOT
-       struct freemem *fmem_2;
-#endif
        registerdata *rd;
        lsradata     *ls;
 
@@ -1352,11 +1349,6 @@ void lsra_alloc(jitdata *jd, int *lifet, int lifetimecount, int *mem_use)
        fmem = DNEW(struct freemem);
        fmem->off  = -1;
        fmem->next = NULL;
-#ifdef HAS_4BYTE_STACKSLOT
-       fmem_2=DNEW(struct freemem);
-       fmem_2->off  = -1;
-       fmem_2->next = NULL;
-#endif
 
        for (lt_index = 0; lt_index < lifetimecount; lt_index ++) {
                lt = &(ls->lifetime[lifet[lt_index]]);
@@ -1365,11 +1357,6 @@ void lsra_alloc(jitdata *jd, int *lifet, int lifetimecount, int *mem_use)
 #endif
                if (lt->reg == -1) {
                        flags = INMEMORY;
-#ifdef HAS_4BYTE_STACKSLOT
-                       if (IS_2_WORD_TYPE(lt->type))
-                               regoff = lsra_getmem(lt, fmem_2, mem_use);
-                       else
-#endif
                        regoff = lsra_getmem(lt, fmem, mem_use);
                } else {
                        flags  = lt->savedvar;
@@ -1411,17 +1398,7 @@ int lsra_getmem(struct lifetime *lt, struct freemem *fmem, int *mem_use)
 
        /* no Memory Slot allocated till now or all are still live */
        if ((fmem->next == NULL) || (fmem->next->end > lt->i_start)) {
-#ifdef HAS_4BYTE_STACKSLOT
-               if (IS_2_WORD_TYPE(lt->type))
-                       if ( (*mem_use)&1 ) /* align memory location for 2 Word Types */
-                               (*mem_use)++;
-               fm=lsra_getnewmem(mem_use);
-               if (IS_2_WORD_TYPE(lt->type))
-                       /* allocate a second following Slot for 2 Word Types */
-                       (*mem_use)++;
-#else
                fm=lsra_getnewmem(mem_use);
-#endif
        } else {
                /* Memoryslot free */
                fm = fmem->next;
@@ -1729,13 +1706,8 @@ void lsra_calc_lifetime_length(jitdata *jd) {
 
                        switch (lt->type) {
                        case TYPE_LNG:
-#if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
-                               flags = 0;
-#else
                                flags = 1;
-#endif
                                break;
-
                        case TYPE_INT:
                        case TYPE_ADR:
                                flags=1;
index d8ccdfa092731464d45867a3a78bc38760371f51..2e555f62e401e27af66482afbd99a38525fe543c 100644 (file)
@@ -35,7 +35,7 @@
 
 #include "mm/memory.h"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/exceptions.hpp"
 #include "vm/method.h"
 #include "vm/options.h"
@@ -44,7 +44,7 @@
 
 #include "vm/jit/abi.h"
 #include "vm/jit/reg.h"
-#include "vm/jit/show.h"
+#include "vm/jit/show.hpp"
 #include "vm/jit/allocator/simplereg.h"
 
 
@@ -64,11 +64,7 @@ static void simplereg_allocate_temporaries(jitdata *jd);
 
 /* size of a stackslot used by the internal ABI */
 
-#if defined(HAS_4BYTE_STACKSLOT)
-# define SIZE_OF_STACKSLOT 4
-#else 
-# define SIZE_OF_STACKSLOT 8
-#endif
+#define SIZE_OF_STACKSLOT 8
 
 
 /* total number of registers */
@@ -207,44 +203,12 @@ static void simplereg_allocate_temporaries(jitdata *jd);
 #define NEW_MEM_SLOT(r)                                              \
     do {                                                             \
         (r) = rd->memuse * SIZE_OF_STACKSLOT;                        \
-        rd->memuse += memneeded + 1;                                 \
-    } while (0)
-
-#define NEW_MEM_SLOT_ALIGNED(r)                                      \
-    do {                                                             \
-        if ( (memneeded) && (rd->memuse & 1))                        \
-            rd->memuse++;                                            \
-        (r) = rd->memuse * SIZE_OF_STACKSLOT;                        \
-        rd->memuse += memneeded + 1;                                 \
+        rd->memuse += 1;                                             \
     } while (0)
 
-#define NEW_MEM_SLOT_ALIGNED_REUSE_PADDING(r)                        \
-    do {                                                             \
-        if ( (memneeded) && (rd->memuse & 1)) {                      \
-                       PUSH_BACK(rd->freemem, rd->freememtop, rd->memuse);      \
-            rd->memuse++;                                            \
-               }                                                            \
-        (r) = rd->memuse * SIZE_OF_STACKSLOT;                        \
-        rd->memuse += memneeded + 1;                                 \
-    } while (0)
-
-#if defined(ALIGN_LONGS_IN_MEMORY)
-#define NEW_MEM_SLOT_INT_LNG(r)  NEW_MEM_SLOT_ALIGNED(r)
-#else
 #define NEW_MEM_SLOT_INT_LNG(r)  NEW_MEM_SLOT(r)
-#endif
-
-#if defined(ALIGN_DOUBLES_IN_MEMORY)
-#define NEW_MEM_SLOT_FLT_DBL(r)  NEW_MEM_SLOT_ALIGNED(r)
-#else
 #define NEW_MEM_SLOT_FLT_DBL(r)  NEW_MEM_SLOT(r)
-#endif
-
-#if defined(ALIGN_LONGS_IN_MEMORY) || defined(ALIGN_DOUBLES_IN_MEMORY)
-#define NEW_MEM_SLOT_REUSE_PADDING(r)  NEW_MEM_SLOT_ALIGNED_REUSE_PADDING(r)
-#else
 #define NEW_MEM_SLOT_REUSE_PADDING(r)  NEW_MEM_SLOT(r)
-#endif
 
 
 /* macros for creating/freeing temporary variables ***************************/
@@ -282,9 +246,9 @@ static void simplereg_allocate_temporaries(jitdata *jd);
 /* regalloc ********************************************************************
 
    Does a simple register allocation.
-       
+
 *******************************************************************************/
-       
+
 bool regalloc(jitdata *jd)
 {
        /* There is a problem with the use of unused float argument
@@ -308,9 +272,9 @@ bool regalloc(jitdata *jd)
 /* simplereg_allocate_interfaces ***********************************************
 
    Allocates registers for all interface variables.
-       
+
 *******************************************************************************/
-       
+
 static void simplereg_allocate_interfaces(jitdata *jd)
 {
        methodinfo   *m;
@@ -321,9 +285,8 @@ static void simplereg_allocate_interfaces(jitdata *jd)
        int     s, t, tt, saved;
        int     intalloc, fltalloc; /* Remember allocated Register/Memory offset */
                        /* in case more vars are packed into this interface slot */
-       int             memneeded = 0;
-       /* Allocate LNG and DBL types first to ensure 2 memory slots or          */
-       /* registers on HAS_4BYTE_STACKSLOT architectures.                       */
+       /* Allocate LNG and DBL types first to ensure 2 registers                */
+       /* on some architectures.                                                */
        int     typeloop[] = { TYPE_LNG, TYPE_DBL, TYPE_INT, TYPE_FLT, TYPE_ADR };
        int     flags, regoff;
 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
@@ -388,10 +351,6 @@ static void simplereg_allocate_interfaces(jitdata *jd)
                        intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
 #endif
 
-#if defined(HAS_4BYTE_STACKSLOT)
-                       memneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
-#endif
-
                        if (!saved) {
 #if defined(HAS_ADDRESS_REGISTER_FILE)
                                if (IS_ADR_TYPE(t)) {
@@ -561,9 +520,9 @@ static void simplereg_allocate_interfaces(jitdata *jd)
 /* simplereg_allocate_locals_leafmethod ****************************************
 
    Allocates registers for all local variables of a leafmethod.
-       
+
 *******************************************************************************/
-       
+
 static void simplereg_allocate_locals_leafmethod(jitdata *jd)
 {
        methodinfo   *m;
@@ -575,7 +534,6 @@ static void simplereg_allocate_locals_leafmethod(jitdata *jd)
        int     intalloc, fltalloc;
        varinfo *v;
        int     intregsneeded = 0;
-       int     memneeded = 0;
        int     typeloop[] = { TYPE_LNG, TYPE_DBL, TYPE_INT, TYPE_FLT, TYPE_ADR };
        int     fargcnt, iargcnt;
 #ifdef HAS_ADDRESS_REGISTER_FILE
@@ -608,9 +566,6 @@ static void simplereg_allocate_locals_leafmethod(jitdata *jd)
 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
                        intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
 #endif
-#if defined(HAS_4BYTE_STACKSLOT)
-                       memneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
-#endif
 
                        /*
                         *  The order of
@@ -769,9 +724,9 @@ static void simplereg_allocate_locals_leafmethod(jitdata *jd)
 /* simplereg_allocate_locals ***************************************************
 
    Allocates registers for all local variables.
-       
+
 *******************************************************************************/
-       
+
 static void simplereg_allocate_locals(jitdata *jd)
 {
        codeinfo     *code;
@@ -781,7 +736,6 @@ static void simplereg_allocate_locals(jitdata *jd)
        int     s, t, tt, varindex;
        int     intalloc, fltalloc;
        varinfo *v;
-       int     memneeded = 0;
        int     typeloop[] = { TYPE_LNG, TYPE_DBL, TYPE_INT, TYPE_FLT, TYPE_ADR };
 #ifdef SUPPORT_COMBINE_INTEGER_REGISTERS
        s4 intregsneeded;
@@ -813,10 +767,6 @@ static void simplereg_allocate_locals(jitdata *jd)
                                intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
 #endif
 
-#if defined(HAS_4BYTE_STACKSLOT)
-                               memneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
-#endif
-
 #ifdef HAS_ADDRESS_REGISTER_FILE
                                if (IS_ADR_TYPE(t)) {
                                        if (AVAIL_SAV_ADR) {
@@ -893,9 +843,6 @@ static void simplereg_init(jitdata *jd, registerdata *rd)
        int i;
 
        rd->freememtop = 0;
-#if defined(HAS_4BYTE_STACKSLOT)
-       rd->freememtop_2 = 0;
-#endif
 
        rd->freetmpinttop = 0;
        rd->freesavinttop = 0;
@@ -1010,7 +957,6 @@ static void simplereg_new_temp(jitdata *jd, s4 index)
 #ifdef SUPPORT_COMBINE_INTEGER_REGISTERS
        s4 intregsneeded;
 #endif
-       s4 memneeded;
        s4 tryagain;
        registerdata *rd;
        varinfo      *v;
@@ -1030,12 +976,6 @@ static void simplereg_new_temp(jitdata *jd, s4 index)
        intregsneeded = (IS_2_WORD_TYPE(v->type)) ? 1 : 0;
 #endif
 
-#if defined(HAS_4BYTE_STACKSLOT)
-       memneeded = (IS_2_WORD_TYPE(v->type)) ? 1 : 0;
-#else
-       memneeded = 0;
-#endif
-
        for(; tryagain; --tryagain) {
                if (tryagain == 1) {
                        if (!(v->flags & SAVEDVAR))
@@ -1156,15 +1096,10 @@ static void simplereg_new_temp(jitdata *jd, s4 index)
 
        v->flags |= INMEMORY;
 
-#if defined(HAS_4BYTE_STACKSLOT)
-       if ((memneeded == 1) && (rd->freememtop_2 > 0))
-               POP_BACK(rd->freemem_2, rd->freememtop_2, v->vv.regoff);
+       if (rd->freememtop > 0)
+               POP_BACK(rd->freemem, rd->freememtop, v->vv.regoff);
        else
-#endif /*defined(HAS_4BYTE_STACKSLOT) */
-               if ((memneeded == 0) && (rd->freememtop > 0))
-                       POP_BACK(rd->freemem, rd->freememtop, v->vv.regoff);
-               else
-                       NEW_MEM_SLOT_REUSE_PADDING(v->vv.regoff);
+               NEW_MEM_SLOT_REUSE_PADDING(v->vv.regoff);
 }
 
 
@@ -1212,13 +1147,7 @@ static void simplereg_free(registerdata *rd, s4 flags, s4 regoff, s4 type)
        }
 
        if (flags & INMEMORY) {
-#if defined(HAS_4BYTE_STACKSLOT)
-               if (IS_2_WORD_TYPE(type))
-                       PUSH_BACK(rd->freemem_2, rd->freememtop_2, regoff);
-               else 
-#endif
-                       PUSH_BACK(rd->freemem, rd->freememtop, regoff);
-
+               PUSH_BACK(rd->freemem, rd->freememtop, regoff);
                return;
        } 
 
index e7f2c44e7ecb38fc6f41aa2efbfbd52dc451f8bf..9ca4373a65fda07b4c20debf2ed17e45cfdce5db 100644 (file)
@@ -1,9 +1,7 @@
 /* src/vm/jit/allocator/simplereg.h - register allocator header
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
-   C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
-   E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
-   J. Wenninger, Institut f. Computersprachen - TU Wien
+   Copyright (C) 1996-2005, 2006, 2008
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
 
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Christian Thalinger
-
-   Changes: Christian Ullrich
-
 */
 
 
 
 #include "arch.h"
 
-#include "vm/jit/codegen-common.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/codegen-common.hpp"
+#include "vm/jit/jit.hpp"
 #include "vm/jit/inline/inline.h"
 
 
 /* function prototypes ********************************************************/
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 bool regalloc(jitdata *jd);
 
 #if defined(ENABLE_STATISTICS)
 void simplereg_make_statistics(jitdata *jd);
 #endif
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* _SIMPLE_REG_H */
 
 
index d9ba3e434584689c3695ec832249380eed2b51aa..1424fc47a045b9960d3cc24ac043904115217d17 100644 (file)
@@ -55,6 +55,7 @@ libarch_la_SOURCES = \
        \
        md-abi.c \
        md-abi.h \
+       md-stubs.hpp \
        md-trap.h \
        md.c \
        md.h
index c2e78ccbef21423971537c549c701c2cc7b04545..f14e210acf05f3e19e6b6863cd19253aad7143d3 100644 (file)
@@ -35,8 +35,6 @@
 
 /* define architecture features ***********************************************/
 
-#define U8_AVAILABLE                     1
-
 #define SUPPORT_DIVISION                 0
 #define SUPPORT_LONG                     1
 
index 8457be0feb9170065c39ac792281e44cbeea7426..6dab39a3c128dbdfbec147101fa9faf808534992 100644 (file)
 
 #include "mm/memory.h"
 
-#include "native/jni.h"
-#include "native/localref.h"
-#include "native/native.h"
+#include "native/localref.hpp"
+#include "native/native.hpp"
 
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/exceptions.hpp"
 #include "vm/global.h"
-#include "vm/loader.h"
+#include "vm/loader.hpp"
 #include "vm/options.h"
 #include "vm/vm.hpp"
 
 #include "vm/jit/abi.h"
 #include "vm/jit/asmpart.h"
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/codegen-common.hpp"
 #include "vm/jit/dseg.h"
-#include "vm/jit/emit-common.h"
-#include "vm/jit/jit.h"
-#include "vm/jit/linenumbertable.h"
+#include "vm/jit/emit-common.hpp"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/linenumbertable.hpp"
 #include "vm/jit/parse.h"
-#include "vm/jit/patcher-common.h"
+#include "vm/jit/patcher-common.hpp"
 #include "vm/jit/reg.h"
-#include "vm/jit/replace.h"
+#include "vm/jit/replace.hpp"
 #include "vm/jit/stacktrace.hpp"
 #include "vm/jit/trap.h"
 
@@ -1116,17 +1115,13 @@ bool codegen_emit(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
-                       if (opt_noieee) {
-                               M_FADD(s1, s2, d);
+                       if (d == s1 || d == s2) {
+                               M_FADDS(s1, s2, REG_FTMP3);
+                               M_TRAPB;
+                               M_FMOV(REG_FTMP3, d);
                        } else {
-                               if (d == s1 || d == s2) {
-                                       M_FADDS(s1, s2, REG_FTMP3);
-                                       M_TRAPB;
-                                       M_FMOV(REG_FTMP3, d);
-                               } else {
-                                       M_FADDS(s1, s2, d);
-                                       M_TRAPB;
-                               }
+                               M_FADDS(s1, s2, d);
+                               M_TRAPB;
                        }
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1136,17 +1131,13 @@ bool codegen_emit(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
-                       if (opt_noieee) {
-                               M_DADD(s1, s2, d);
+                       if (d == s1 || d == s2) {
+                               M_DADDS(s1, s2, REG_FTMP3);
+                               M_TRAPB;
+                               M_FMOV(REG_FTMP3, d);
                        } else {
-                               if (d == s1 || d == s2) {
-                                       M_DADDS(s1, s2, REG_FTMP3);
-                                       M_TRAPB;
-                                       M_FMOV(REG_FTMP3, d);
-                               } else {
-                                       M_DADDS(s1, s2, d);
-                                       M_TRAPB;
-                               }
+                               M_DADDS(s1, s2, d);
+                               M_TRAPB;
                        }
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1156,17 +1147,13 @@ bool codegen_emit(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
-                       if (opt_noieee) {
-                               M_FSUB(s1, s2, d);
+                       if (d == s1 || d == s2) {
+                               M_FSUBS(s1, s2, REG_FTMP3);
+                               M_TRAPB;
+                               M_FMOV(REG_FTMP3, d);
                        } else {
-                               if (d == s1 || d == s2) {
-                                       M_FSUBS(s1, s2, REG_FTMP3);
-                                       M_TRAPB;
-                                       M_FMOV(REG_FTMP3, d);
-                               } else {
-                                       M_FSUBS(s1, s2, d);
-                                       M_TRAPB;
-                               }
+                               M_FSUBS(s1, s2, d);
+                               M_TRAPB;
                        }
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1176,17 +1163,13 @@ bool codegen_emit(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
-                       if (opt_noieee) {
-                               M_DSUB(s1, s2, d);
+                       if (d == s1 || d == s2) {
+                               M_DSUBS(s1, s2, REG_FTMP3);
+                               M_TRAPB;
+                               M_FMOV(REG_FTMP3, d);
                        } else {
-                               if (d == s1 || d == s2) {
-                                       M_DSUBS(s1, s2, REG_FTMP3);
-                                       M_TRAPB;
-                                       M_FMOV(REG_FTMP3, d);
-                               } else {
-                                       M_DSUBS(s1, s2, d);
-                                       M_TRAPB;
-                               }
+                               M_DSUBS(s1, s2, d);
+                               M_TRAPB;
                        }
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1196,17 +1179,13 @@ bool codegen_emit(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
-                       if (opt_noieee) {
-                               M_FMUL(s1, s2, d);
+                       if (d == s1 || d == s2) {
+                               M_FMULS(s1, s2, REG_FTMP3);
+                               M_TRAPB;
+                               M_FMOV(REG_FTMP3, d);
                        } else {
-                               if (d == s1 || d == s2) {
-                                       M_FMULS(s1, s2, REG_FTMP3);
-                                       M_TRAPB;
-                                       M_FMOV(REG_FTMP3, d);
-                               } else {
-                                       M_FMULS(s1, s2, d);
-                                       M_TRAPB;
-                               }
+                               M_FMULS(s1, s2, d);
+                               M_TRAPB;
                        }
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1216,17 +1195,13 @@ bool codegen_emit(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
-                       if (opt_noieee) {
-                               M_DMUL(s1, s2, d);
+                       if (d == s1 || d == s2) {
+                               M_DMULS(s1, s2, REG_FTMP3);
+                               M_TRAPB;
+                               M_FMOV(REG_FTMP3, d);
                        } else {
-                               if (d == s1 || d == s2) {
-                                       M_DMULS(s1, s2, REG_FTMP3);
-                                       M_TRAPB;
-                                       M_FMOV(REG_FTMP3, d);
-                               } else {
-                                       M_DMULS(s1, s2, d);
-                                       M_TRAPB;
-                               }
+                               M_DMULS(s1, s2, d);
+                               M_TRAPB;
                        }
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1236,17 +1211,13 @@ bool codegen_emit(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
-                       if (opt_noieee) {
-                               M_FDIV(s1, s2, d);
+                       if (d == s1 || d == s2) {
+                               M_FDIVS(s1, s2, REG_FTMP3);
+                               M_TRAPB;
+                               M_FMOV(REG_FTMP3, d);
                        } else {
-                               if (d == s1 || d == s2) {
-                                       M_FDIVS(s1, s2, REG_FTMP3);
-                                       M_TRAPB;
-                                       M_FMOV(REG_FTMP3, d);
-                               } else {
-                                       M_FDIVS(s1, s2, d);
-                                       M_TRAPB;
-                               }
+                               M_FDIVS(s1, s2, d);
+                               M_TRAPB;
                        }
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1256,17 +1227,13 @@ bool codegen_emit(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
-                       if (opt_noieee) {
-                               M_DDIV(s1, s2, d);
+                       if (d == s1 || d == s2) {
+                               M_DDIVS(s1, s2, REG_FTMP3);
+                               M_TRAPB;
+                               M_FMOV(REG_FTMP3, d);
                        } else {
-                               if (d == s1 || d == s2) {
-                                       M_DDIVS(s1, s2, REG_FTMP3);
-                                       M_TRAPB;
-                                       M_FMOV(REG_FTMP3, d);
-                               } else {
-                                       M_DDIVS(s1, s2, d);
-                                       M_TRAPB;
-                               }
+                               M_DDIVS(s1, s2, d);
+                               M_TRAPB;
                        }
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1329,12 +1296,8 @@ bool codegen_emit(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
-                       if (opt_noieee) {
-                               M_CVTDF(s1, d);
-                       } else {
-                               M_CVTDFS(s1, d);
-                               M_TRAPB;
-                       }
+                       M_CVTDFS(s1, d);
+                       M_TRAPB;
                        emit_store_dst(jd, iptr, d);
                        break;
                
@@ -1343,25 +1306,15 @@ bool codegen_emit(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
-                       if (opt_noieee) {
-                               M_LSUB_IMM(REG_ZERO, 1, d);
-                               M_FCMPEQ(s1, s2, REG_FTMP3);
-                               M_FBEQZ (REG_FTMP3, 1);        /* jump over next instructions */
-                               M_CLR   (d);
-                               M_FCMPLT(s2, s1, REG_FTMP3);
-                               M_FBEQZ (REG_FTMP3, 1);        /* jump over next instruction  */
-                               M_LADD_IMM(REG_ZERO, 1, d);
-                       } else {
-                               M_LSUB_IMM(REG_ZERO, 1, d);
-                               M_FCMPEQS(s1, s2, REG_FTMP3);
-                               M_TRAPB;
-                               M_FBEQZ (REG_FTMP3, 1);        /* jump over next instructions */
-                               M_CLR   (d);
-                               M_FCMPLTS(s2, s1, REG_FTMP3);
-                               M_TRAPB;
-                               M_FBEQZ (REG_FTMP3, 1);        /* jump over next instruction  */
-                               M_LADD_IMM(REG_ZERO, 1, d);
-                       }
+                       M_LSUB_IMM(REG_ZERO, 1, d);
+                       M_FCMPEQS(s1, s2, REG_FTMP3);
+                       M_TRAPB;
+                       M_FBEQZ (REG_FTMP3, 1);        /* jump over next instructions */
+                       M_CLR   (d);
+                       M_FCMPLTS(s2, s1, REG_FTMP3);
+                       M_TRAPB;
+                       M_FBEQZ (REG_FTMP3, 1);        /* jump over next instruction  */
+                       M_LADD_IMM(REG_ZERO, 1, d);
                        emit_store_dst(jd, iptr, d);
                        break;
                        
@@ -1370,25 +1323,15 @@ bool codegen_emit(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
-                       if (opt_noieee) {
-                               M_LADD_IMM(REG_ZERO, 1, d);
-                               M_FCMPEQ(s1, s2, REG_FTMP3);
-                               M_FBEQZ (REG_FTMP3, 1);        /* jump over next instruction  */
-                               M_CLR   (d);
-                               M_FCMPLT(s1, s2, REG_FTMP3);
-                               M_FBEQZ (REG_FTMP3, 1);        /* jump over next instruction  */
-                               M_LSUB_IMM(REG_ZERO, 1, d);
-                       } else {
-                               M_LADD_IMM(REG_ZERO, 1, d);
-                               M_FCMPEQS(s1, s2, REG_FTMP3);
-                               M_TRAPB;
-                               M_FBEQZ (REG_FTMP3, 1);        /* jump over next instruction  */
-                               M_CLR   (d);
-                               M_FCMPLTS(s1, s2, REG_FTMP3);
-                               M_TRAPB;
-                               M_FBEQZ (REG_FTMP3, 1);        /* jump over next instruction  */
-                               M_LSUB_IMM(REG_ZERO, 1, d);
-                       }
+                       M_LADD_IMM(REG_ZERO, 1, d);
+                       M_FCMPEQS(s1, s2, REG_FTMP3);
+                       M_TRAPB;
+                       M_FBEQZ (REG_FTMP3, 1);        /* jump over next instruction  */
+                       M_CLR   (d);
+                       M_FCMPLTS(s1, s2, REG_FTMP3);
+                       M_TRAPB;
+                       M_FBEQZ (REG_FTMP3, 1);        /* jump over next instruction  */
+                       M_LSUB_IMM(REG_ZERO, 1, d);
                        emit_store_dst(jd, iptr, d);
                        break;
 
index c43ba7b6d56574ea5e20fd3e402a99be17f594a3..17953240b186e95ed0f8fb61e39ec8ae4b3d7ceb 100644 (file)
@@ -1,9 +1,8 @@
 /* src/vm/jit/alpha/codegen.h - code generation macros and definitions for Alpha
 
-   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
-   C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
-   E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
-   J. Wenninger, Institut f. Computersprachen - TU Wien
+   Copyright (C) 1996-2005, 2006, 2007
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+   Copyright (C) 2008 Theobroma Systems Ltd.
 
    This file is part of CACAO.
 
@@ -31,7 +30,7 @@
 #include "config.h"
 #include "vm/types.h"
 
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
 
 
 /* additional functions and macros to generate code ***************************/
     } while (0)
 
 
-/* stub defines ***************************************************************/
-
-#define COMPILERSTUB_CODESIZE    1 * 4
-
-
 /* macros to create code ******************************************************/
 
 /* M_MEM - memory instruction format *******************************************
         cd->mcodeptr += 4; \
     } while (0)
 
+#define M_OP3_GET_Opcode(x)             (          (((x) >> 26) & 0x3f  ))
+
 
 /* 3-address-floating-point-operation: M_FOP3 
      op .... opcode
 
 #define M_FBEQZ(fa,disp)        M_BRA (0x31,fa,disp)            /* br a == 0.0*/
 
-/* macros for special commands (see an Alpha-manual for description) **********/ 
+/* macros for special commands (see an Alpha-manual for description) **********/
 
 #define M_TRAPB                 M_MEM (0x18,0,0,0x0000)        /* trap barrier*/
 
 #define M_CMOVLE_IMM(a,b,c)     M_OP3 (0x11,0x64, a,b,c,1)     /* a<=0 ? c=b  */
 #define M_CMOVGT_IMM(a,b,c)     M_OP3 (0x11,0x66, a,b,c,1)     /* a> 0 ? c=b  */
 
+// 0x04 seems to be the first undefined instruction which does not
+// call PALcode.
+#define M_UNDEFINED             M_OP3(0x04, 0, 0, 0, 0, 0)
+
 /* macros for unused commands (see an Alpha-manual for description) ***********/
 
 #define M_ANDNOT(a,b,c,const)   M_OP3 (0x11,0x08, a,b,c,const) /* c = a &~ b  */
index 4f2f540d8304bf783c1a443d0e09eec7455399b6..8bf59e90e858c4fce000427a83bc9bb62b1c70b9 100644 (file)
@@ -35,7 +35,7 @@
 
 #include "mm/memory.h"
 
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
 
 #include "vm/options.h"
 
 #include "vm/jit/abi-asm.h"
 #include "vm/jit/asmpart.h"
 #include "vm/jit/dseg.h"
-#include "vm/jit/emit-common.h"
-#include "vm/jit/jit.h"
-#include "vm/jit/patcher-common.h"
-#include "vm/jit/replace.h"
+#include "vm/jit/emit-common.hpp"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/patcher-common.hpp"
+#include "vm/jit/replace.hpp"
 #include "vm/jit/trace.hpp"
 #include "vm/jit/trap.h"
 
@@ -446,11 +446,10 @@ uint32_t emit_trap(codegendata *cd)
        /* Get machine code which is patched back in later. The
           trap is 1 instruction word long. */
 
-       mcode = *((uint32_t *) cd->mcodeptr);
+       mcode = *((uint32_t*) cd->mcodeptr);
 
-       /* Destination register must not be REG_ZERO, because then no
-          SIGSEGV is thrown. */
-       M_ALD_INTERN(REG_RESULT, REG_ZERO, TRAP_PATCHER);
+       // Generate a SIGILL.
+       M_UNDEFINED;
 
        return mcode;
 }
index d752d57fccde5d6ebd348be135b1db39918ef00e..8e127a9fab4e3bae10487216f640ecdda617c28a 100644 (file)
@@ -2,6 +2,7 @@
 
    Copyright (C) 1996-2005, 2006, 2007, 2008
    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+   Copyright (C) 2008 Theobroma Systems Ltd.
 
    This file is part of CACAO.
 
 
 #include "threads/thread.hpp"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/signallocal.h"
 #include "vm/os.hpp"
 
 #include "vm/jit/asmpart.h"
+#include "vm/jit/disass.h"
 #include "vm/jit/executionstate.h"
 #include "vm/jit/trap.h"
 
@@ -68,7 +70,6 @@ void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
        intptr_t        val;
        intptr_t        addr;
        int             type;
-       void           *p;
 
        _uc = (ucontext_t *) _p;
        _mc = &_uc->uc_mcontext;
@@ -112,43 +113,50 @@ void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
 
        /* Handle the trap. */
 
-       p = trap_handle(type, val, pv, sp, ra, xpc, _p);
-
-       /* Set registers. */
+       trap_handle(type, val, pv, sp, ra, xpc, _p);
+}
 
-       switch (type) {
-       case TRAP_COMPILER:
-               if (p != NULL) {
-                       _mc->sc_regs[REG_PV] = (uintptr_t) p;
-                       _mc->sc_pc           = (uintptr_t) p;
-                       break;
-               }
 
-               /* Get and set the PV from the parent Java method. */
+/* md_signal_handler_sigill ****************************************************
 
-               pv = md_codegen_get_pv_from_pc(ra);
+   Illegal Instruction signal handler for hardware exception checks.
 
-               _mc->sc_regs[REG_PV] = (uintptr_t) pv;
+*******************************************************************************/
 
-               /* Get the exception object. */
+void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p)
+{
+       ucontext_t* _uc = (ucontext_t*) _p;
+       mcontext_t* _mc = &_uc->uc_mcontext;
 
-               p = builtin_retrieve_exception();
+       void* pv  = (u1 *) _mc->sc_regs[REG_PV];
+       void* sp  = (u1 *) _mc->sc_regs[REG_SP];
+       void* ra  = (u1 *) _mc->sc_regs[REG_RA]; // RA is correct for leaf methods.
+       void* xpc = (u1 *) _mc->sc_pc;
 
-               assert(p != NULL);
+       // The PC points to the instruction after the illegal instruction.
+       xpc = (void*) (((uintptr_t) xpc) - 4);
 
-               /* fall-through */
+       // Get the exception-throwing instruction.
+       uint32_t mcode = *((uint32_t*) xpc);
 
-       case TRAP_PATCHER:
-               if (p == NULL)
-                       break;
+       int opcode = M_OP3_GET_Opcode(mcode);
 
-               /* fall-through */
-               
-       default:
-               _mc->sc_regs[REG_ITMP1_XPTR] = (uintptr_t) p;
-               _mc->sc_regs[REG_ITMP2_XPC]  = (uintptr_t) xpc;
-               _mc->sc_pc                   = (uintptr_t) asm_handle_exception;
+       // Check for undefined instruction we use.
+       // TODO Check the whole instruction.
+       if (opcode != 0x4) {
+               log_println("md_signal_handler_sigill: Unknown illegal instruction %x at %p", mcode, xpc);
+#if defined(ENABLE_DISASSEMBLER)
+               (void) disassinstr(xpc);
+#endif
+               vm_abort("Aborting...");
        }
+
+       // This signal is always a patcher.
+       int      type = TRAP_PATCHER;
+       intptr_t val  = 0;
+
+       // Handle the trap.
+       trap_handle(type, val, pv, sp, ra, xpc, _p);
 }
 
 
diff --git a/src/vm/jit/alpha/md-stubs.hpp b/src/vm/jit/alpha/md-stubs.hpp
new file mode 100644 (file)
index 0000000..8ff379f
--- /dev/null
@@ -0,0 +1,56 @@
+/* src/vm/jit/alpha/md-stubs.hpp - Alpha JIT stubs
+
+   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 _MD_STUBS_HPP
+#define _MD_STUBS_HPP
+
+#include "config.h"
+
+
+/**
+ * Return the code size of a compiler on an Alpha architecture.
+ *
+ * @return Code size in bytes.
+ */
+int CompilerStub::get_code_size()
+{
+       return 1 * 4;
+}
+
+#endif // _MD_STUBS_HPP
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
index 2958813c47ee7fad1d2dbb46fce1bce23dfbd051..9ad99b7474b6f982d1c66ea557be178a04f453a7 100644 (file)
@@ -39,7 +39,7 @@ extern void ieee_set_fp_control(unsigned long fp_control);
 #include "vm/jit/alpha/md.h"
 
 #include "vm/jit/asmpart.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
 #include "vm/jit/trap.h"
 
 
index da186e3c0560a7efcf4c197104056e0f82ed8573..e939d3803677cc45c07092b70cbb23d87038db05 100644 (file)
@@ -37,7 +37,7 @@
 #include "vm/vm.hpp"
 
 #include "vm/jit/asmpart.h"
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/codegen-common.hpp"
 
 
 /* global variables ***********************************************************/
index 0e981a090e92ecbe28245a668f74441cac933023..71368b63e07b3cc79d832905818adc8d4b16818d 100644 (file)
 
 #include "mm/memory.h"
 
-#include "native/native.h"
+#include "native/native.hpp"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/class.h"
-#include "vm/field.h"
+#include "vm/field.hpp"
 #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/patcher-common.hpp"
 #include "vm/jit/methodheader.h"
 
 
-#define PATCH_BACK_ORIGINAL_MCODE \
-       *((u4 *) pr->mpc) = (u4) pr->mcode; \
-    md_icacheflush(NULL, 0);
-
-
 /* patcher_patch_code **********************************************************
 
    Just patches back the original machine code.
 
 *******************************************************************************/
 
-void patcher_patch_code(patchref_t *pr)
+void patcher_patch_code(patchref_tpr)
 {
-       PATCH_BACK_ORIGINAL_MCODE;
+       // Patch back original code.
+       *((uint32_t*) pr->mpc) = pr->mcode;
+
+       // Synchronize instruction cache.
+    md_icacheflush(NULL, 0);
 }
 
 
@@ -105,12 +104,13 @@ bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
        if (!(c = resolve_classref_eager(cr)))
                return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
-
        /* patch the classinfo pointer */
 
        *((ptrint *) datap) = (ptrint) c;
 
+       // Patch back the original code.
+       patcher_patch_code(pr);
+
        return true;
 }
 
@@ -142,12 +142,13 @@ bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
        if (!(c = resolve_classref_eager(cr)))
                return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
-
        /* patch super class' vftbl */
 
        *((ptrint *) datap) = (ptrint) c->vftbl;
 
+       // Patch back the original code.
+       patcher_patch_code(pr);
+
        return true;
 }
 
@@ -176,12 +177,13 @@ bool patcher_resolve_classref_to_flags(patchref_t *pr)
        if (!(c = resolve_classref_eager(cr)))
                return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
-
        /* patch class flags */
 
        *((s4 *) datap) = (s4) c->flags;
 
+       // Patch back the original code.
+       patcher_patch_code(pr);
+
        return true;
 }
 
@@ -218,12 +220,13 @@ bool patcher_get_putstatic(patchref_t *pr)
                if (!initialize_class(fi->clazz))
                        return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
-
        /* patch the field value's address */
 
        *((intptr_t *) datap) = (intptr_t) fi->value;
 
+       // Patch back the original code.
+       patcher_patch_code(pr);
+
        return true;
 }
 
@@ -239,11 +242,9 @@ bool patcher_get_putstatic(patchref_t *pr)
 
 bool patcher_get_putfield(patchref_t *pr)
 {
-       u1               *ra;
        unresolved_field *uf;
        fieldinfo        *fi;
 
-       ra    = (u1 *)               pr->mpc;
        uf    = (unresolved_field *) pr->ref;
 
        /* get the fieldinfo */
@@ -251,18 +252,12 @@ bool patcher_get_putfield(patchref_t *pr)
        if (!(fi = resolve_field_eager(uf)))
                return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
-
-       /* if we show disassembly, we have to skip the nop */
-
-       if (opt_shownops)
-               ra = ra + 4;
-
        /* patch the field's offset into the instruction */
 
-       *((u4 *) ra) |= (s2) (fi->offset & 0x0000ffff);
+       pr->mcode |= (s2) (fi->offset & 0x0000ffff);
 
-       md_icacheflush(NULL, 0);
+       // Patch back the original code.
+       patcher_patch_code(pr);
 
        return true;
 }
@@ -294,12 +289,13 @@ bool patcher_invokestatic_special(patchref_t *pr)
        if (!(m = resolve_method_eager(um)))
                return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
-
        /* patch stubroutine */
 
        *((ptrint *) datap) = (ptrint) m->stubroutine;
 
+       // Patch back the original code.
+       patcher_patch_code(pr);
+
        return true;
 }
 
@@ -331,13 +327,6 @@ bool patcher_invokevirtual(patchref_t *pr)
        if (!(m = resolve_method_eager(um)))
                return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
-
-       /* if we show disassembly, we have to skip the nop */
-
-       if (opt_shownops)
-               ra = ra + 4;
-
        /* patch vftbl index */
 
        *((s4 *) (ra + 4)) |= (s4) ((OFFSET(vftbl_t, table[0]) +
@@ -345,6 +334,9 @@ bool patcher_invokevirtual(patchref_t *pr)
 
        md_icacheflush(NULL, 0);
 
+       // Patch back the original code.
+       patcher_patch_code(pr);
+
        return true;
 }
 
@@ -377,13 +369,6 @@ bool patcher_invokeinterface(patchref_t *pr)
        if (!(m = resolve_method_eager(um)))
                return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
-
-       /* if we show disassembly, we have to skip the nop */
-
-       if (opt_shownops)
-               ra = ra + 4;
-
        /* patch interfacetable index */
 
        *((s4 *) (ra + 4)) |= (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
@@ -396,6 +381,9 @@ bool patcher_invokeinterface(patchref_t *pr)
 
        md_icacheflush(NULL, 0);
 
+       // Patch back the original code.
+       patcher_patch_code(pr);
+
        return true;
 }
 
@@ -429,13 +417,6 @@ bool patcher_checkcast_interface(patchref_t *pr)
        if (!(c = resolve_classref_eager(cr)))
                return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
-
-       /* if we show disassembly, we have to skip the nop */
-
-       if (opt_shownops)
-               ra = ra + 4;
-
        /* patch super class index */
 
        *((s4 *) (ra + 2 * 4)) |= (s4) (-(c->index) & 0x0000ffff);
@@ -445,6 +426,9 @@ bool patcher_checkcast_interface(patchref_t *pr)
 
        md_icacheflush(NULL, 0);
 
+       // Patch back the original code.
+       patcher_patch_code(pr);
+
        return true;
 }
 
@@ -478,13 +462,6 @@ bool patcher_instanceof_interface(patchref_t *pr)
        if (!(c = resolve_classref_eager(cr)))
                return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
-
-       /* if we show disassembly, we have to skip the nop */
-
-       if (opt_shownops)
-               ra = ra + 4;
-
        /* patch super class index */
 
        *((s4 *) (ra + 2 * 4)) |= (s4) (-(c->index) & 0x0000ffff);
@@ -494,6 +471,9 @@ bool patcher_instanceof_interface(patchref_t *pr)
 
        md_icacheflush(NULL, 0);
 
+       // Patch back the original code.
+       patcher_patch_code(pr);
+
        return true;
 }
 
diff --git a/src/vm/jit/argument.c b/src/vm/jit/argument.c
deleted file mode 100644 (file)
index dbee5fa..0000000
+++ /dev/null
@@ -1,770 +0,0 @@
-/* src/vm/jit/argument.c - argument passing from and to JIT methods
-
-   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 "arch.h"
-
-#include "mm/memory.h"
-
-#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"
-
-
-/* argument_jitarray_load ******************************************************
-   Returns the argument specified by index from one of the passed arrays
-   and returns it.
-
-*******************************************************************************/
-
-imm_union argument_jitarray_load(methoddesc *md, int32_t index,
-                                                                uint64_t *arg_regs, uint64_t *stack)
-{
-       imm_union  ret;
-       paramdesc *pd;
-
-       pd = &md->params[index];
-
-       switch (md->paramtypes[index].type) {
-               case TYPE_INT:
-               case TYPE_ADR:
-                       if (pd->inmemory) {
-#if (SIZEOF_VOID_P == 8)
-                               ret.l = (int64_t)stack[pd->index];
-#else
-                               ret.l = *(int32_t *)(stack + pd->index);
-#endif
-                       } else {
-#if (SIZEOF_VOID_P == 8)
-                               ret.l = arg_regs[index];
-#else
-                               ret.l = *(int32_t *)(arg_regs + index);
-#endif
-                       }
-                       break;
-               case TYPE_LNG:
-                       if (pd->inmemory) {
-                               ret.l = (int64_t)stack[pd->index];
-                       } else {
-                               ret.l = (int64_t)arg_regs[index];
-                       }
-                       break;
-               case TYPE_FLT:
-                       if (pd->inmemory) {
-                               ret.l = (int64_t)stack[pd->index];
-                       } else {
-                               ret.l = (int64_t)arg_regs[index];
-                       }
-                       break;
-               case TYPE_DBL:
-                       if (pd->inmemory) {
-                               ret.l = (int64_t)stack[pd->index];
-                       } else {
-                               ret.l = (int64_t)arg_regs[index];
-                       }
-                       break;
-       }
-
-       return ret;
-}
-
-
-/* argument_jitarray_store *****************************************************
-   Stores the argument into one of the passed arrays at a slot specified
-   by index.
-
-*******************************************************************************/
-
-void argument_jitarray_store(methoddesc *md, int32_t index,
-                                                        uint64_t *arg_regs, uint64_t *stack,
-                                                        imm_union param)
-{
-       paramdesc *pd;
-
-       pd = &md->params[index];
-
-       switch (md->paramtypes[index].type) {
-               case TYPE_ADR:
-                       if (pd->inmemory) {
-#if (SIZEOF_VOID_P == 8)
-                               stack[pd->index] = param.l;
-#else
-                               assert(0);
-#endif
-                       } else {
-                               arg_regs[index] = param.l;
-                       }
-                       break;
-               default:
-                       vm_abort("argument_jitarray_store: type not implemented");
-                       break;
-       }
-}
-
-
-/* argument_jitreturn_load *****************************************************
-
-   Loads the proper return value form the return register and returns it.
-
-*******************************************************************************/
-
-imm_union argument_jitreturn_load(methoddesc *md, uint64_t *return_regs)
-{
-       imm_union ret;
-
-       switch (md->returntype.type) {
-               case TYPE_INT:
-               case TYPE_ADR:
-#if (SIZEOF_VOID_P == 8)
-                       ret.l = return_regs[0];
-#else
-                       ret.l = *(int32_t *)return_regs;
-#endif
-                       break;
-               case TYPE_LNG:
-                       ret.l = *(int64_t *)return_regs;
-                       break;
-               case TYPE_FLT:
-                       ret.l = *(int64_t *)return_regs;
-                       break;
-               case TYPE_DBL:
-                       ret.l = *(int64_t *)return_regs;
-                       break;
-       }
-
-       return ret;
-}
-
-
-/* argument_jitreturn_store ****************************************************
-
-   Stores the proper return value into the return registers.
-
-*******************************************************************************/
-
-void argument_jitreturn_store(methoddesc *md, uint64_t *return_regs, imm_union ret)
-{
-       switch (md->returntype.type) {
-               case TYPE_ADR:
-#if (SIZEOF_VOID_P == 8)
-                       return_regs[0] = ret.l;
-#else
-                       assert(0);
-#endif
-                       break;
-               default:
-                       vm_abort("argument_jitreturn_store: type not implemented");
-                       break;
-       }
-}
-
-
-/* argument_vmarray_store_int **************************************************
-
-   Helper function to store an integer into the argument array, taking
-   care of architecture specific issues.
-
-*******************************************************************************/
-
-static void argument_vmarray_store_int(uint64_t *array, paramdesc *pd, int32_t value)
-{
-       int32_t index;
-
-       if (!pd->inmemory) {
-               index        = pd->index;
-               array[index] = (int64_t) value;
-       }
-       else {
-               index        = ARG_CNT + pd->index;
-#if SIZEOF_VOID_P == 8
-               array[index] = (int64_t) value;
-#else
-# if WORDS_BIGENDIAN == 1
-               array[index] = ((int64_t) value) << 32;
-# else
-               array[index] = (int64_t) value;
-# endif
-#endif
-       }
-}
-
-
-/* argument_vmarray_store_lng **************************************************
-
-   Helper function to store a long into the argument array, taking
-   care of architecture specific issues.
-
-*******************************************************************************/
-
-static void argument_vmarray_store_lng(uint64_t *array, paramdesc *pd, int64_t value)
-{
-       int32_t index;
-
-#if SIZEOF_VOID_P == 8
-       if (!pd->inmemory)
-               index = pd->index;
-       else
-               index = ARG_CNT + pd->index;
-
-       array[index] = value;
-#else
-       if (!pd->inmemory) {
-               /* move low and high 32-bits into it's own argument slot */
-
-               index        = GET_LOW_REG(pd->index);
-               array[index] = value & 0x00000000ffffffff;
-
-               index        = GET_HIGH_REG(pd->index);
-               array[index] = value >> 32;
-       }
-       else {
-               index        = ARG_CNT + pd->index;
-               array[index] = value;
-       }
-#endif
-}
-
-
-/* argument_vmarray_store_flt **************************************************
-
-   Helper function to store a float into the argument array, taking
-   care of architecture specific issues.
-
-*******************************************************************************/
-
-static void argument_vmarray_store_flt(uint64_t *array, paramdesc *pd, uint64_t value)
-{
-       int32_t index;
-
-       if (!pd->inmemory) {
-#if defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS)
-               index        = pd->index;
-#else
-               index        = INT_ARG_CNT + pd->index;
-#endif
-#if WORDS_BIGENDIAN == 1 && !defined(__POWERPC__) && !defined(__POWERPC64__) && !defined(__S390__)
-               array[index] = value >> 32;
-#else
-               array[index] = value;
-#endif
-       }
-       else {
-               index        = ARG_CNT + pd->index;
-#if defined(__SPARC_64__)
-               array[index] = value >> 32;
-#else
-               array[index] = value;
-#endif
-       }
-}
-
-
-/* argument_vmarray_store_dbl **************************************************
-
-   Helper function to store a double into the argument array, taking
-   care of architecture specific issues.
-
-*******************************************************************************/
-
-static void argument_vmarray_store_dbl(uint64_t *array, paramdesc *pd, uint64_t value)
-{
-       int32_t index;
-
-       if (!pd->inmemory) {
-#if SIZEOF_VOID_P != 8 && defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS)
-               index        = GET_LOW_REG(pd->index);
-               array[index] = value & 0x00000000ffffffff;
-
-               index        = GET_HIGH_REG(pd->index);
-               array[index] = value >> 32;
-#else
-               index        = INT_ARG_CNT + pd->index;
-               array[index] = value;
-#endif
-       }
-       else {
-               index        = ARG_CNT + pd->index;
-               array[index] = value;
-       }
-}
-
-
-/* argument_vmarray_store_adr **************************************************
-
-   Helper function to store an address into the argument array, taking
-   care of architecture specific issues.
-
-   ATTENTION: This function has to be used outside the nativeworld.
-
-*******************************************************************************/
-
-static void argument_vmarray_store_adr(uint64_t *array, paramdesc *pd, java_handle_t *h)
-{
-       void    *value;
-       int32_t  index;
-
-       /* Take the reference value out of the handle. */
-
-       value = LLNI_UNWRAP(h);
-
-       if (!pd->inmemory) {
-#if defined(HAS_ADDRESS_REGISTER_FILE)
-               /* When the architecture has address registers, place them
-                  after integer and float registers. */
-
-               index        = INT_ARG_CNT + FLT_ARG_CNT + pd->index;
-#else
-               index        = pd->index;
-#endif
-               array[index] = (uint64_t) (intptr_t) value;
-       }
-       else {
-               index        = ARG_CNT + pd->index;
-#if SIZEOF_VOID_P == 8
-               array[index] = (uint64_t) (intptr_t) value;
-#else
-# if WORDS_BIGENDIAN == 1
-               array[index] = ((uint64_t) (intptr_t) value) << 32;
-# else
-               array[index] = (uint64_t) (intptr_t) value;
-# endif
-#endif
-       }
-}
-
-
-/* argument_vmarray_from_valist ************************************************
-
-   Creates an argument array which can be passed to asm_vm_call_method.
-   The array is created from the passed valist.
-
-   ATTENTION: This function has to be used outside the native world.
-
-*******************************************************************************/
-
-uint64_t *argument_vmarray_from_valist(methodinfo *m, java_handle_t *o, va_list ap)
-{
-       methoddesc *md;
-       paramdesc  *pd;
-       typedesc   *td;
-       uint64_t   *array;
-       int32_t     i;
-       imm_union   value;
-
-       /* get the descriptors */
-
-       md = m->parseddesc;
-       pd = md->params;
-       td = md->paramtypes;
-
-       /* allocate argument array */
-
-       array = DMNEW(uint64_t, INT_ARG_CNT + FLT_ARG_CNT + md->memuse);
-
-       /* if method is non-static fill first block and skip `this' pointer */
-
-       i = 0;
-
-       if (o != NULL) {
-               /* the `this' pointer */
-               argument_vmarray_store_adr(array, pd, o);
-
-               pd++;
-               td++;
-               i++;
-       } 
-
-       for (; i < md->paramcount; i++, pd++, td++) {
-               switch (td->type) {
-               case TYPE_INT:
-                       value.i = va_arg(ap, int32_t);
-                       argument_vmarray_store_int(array, pd, value.i);
-                       break;
-
-               case TYPE_LNG:
-                       value.l = va_arg(ap, int64_t);
-                       argument_vmarray_store_lng(array, pd, value.l);
-                       break;
-
-               case TYPE_FLT:
-#if defined(__ALPHA__) || defined(__POWERPC__) || defined(__POWERPC64__)
-                       /* This is required to load the correct float value in
-                          assembler code. */
-
-                       value.d = (double) va_arg(ap, double);
-#else
-                       value.f = (float) va_arg(ap, double);
-#endif
-                       argument_vmarray_store_flt(array, pd, value.l);
-                       break;
-
-               case TYPE_DBL:
-                       value.d = va_arg(ap, double);
-                       argument_vmarray_store_dbl(array, pd, value.l);
-                       break;
-
-               case TYPE_ADR: 
-                       value.a = va_arg(ap, void*);
-                       argument_vmarray_store_adr(array, pd, value.a);
-                       break;
-               }
-       }
-
-       return array;
-}
-
-
-/* argument_vmarray_from_jvalue ************************************************
-
-   Creates an argument array which can be passed to asm_vm_call_method.
-   The array is created from the passed jvalue array.
-
-   ATTENTION: This function has to be used outside the native world.
-
-*******************************************************************************/
-
-uint64_t *argument_vmarray_from_jvalue(methodinfo *m, java_handle_t *o,
-                                                                          const jvalue *args)
-{
-       methoddesc *md;
-       paramdesc  *pd;
-       typedesc   *td;
-       uint64_t   *array;
-       int32_t     i;
-       int32_t     j;
-
-       /* get the descriptors */
-
-       md = m->parseddesc;
-       pd = md->params;
-       td = md->paramtypes;
-
-       /* allocate argument array */
-
-#if defined(HAS_ADDRESS_REGISTER_FILE)
-       array = DMNEW(uint64_t, INT_ARG_CNT + FLT_ARG_CNT + ADR_ARG_CNT + md->memuse);
-#else
-       array = DMNEW(uint64_t, INT_ARG_CNT + FLT_ARG_CNT + md->memuse);
-#endif
-
-       /* if method is non-static fill first block and skip `this' pointer */
-
-       i = 0;
-
-       if (o != NULL) {
-               /* the `this' pointer */
-               argument_vmarray_store_adr(array, pd, o);
-
-               pd++;
-               td++;
-               i++;
-       } 
-
-       for (j = 0; i < md->paramcount; i++, j++, pd++, td++) {
-               switch (td->primitivetype) {
-               case TYPE_INT:
-                       argument_vmarray_store_int(array, pd, args[j].i);
-                       break;
-
-               case TYPE_LNG:
-                       argument_vmarray_store_lng(array, pd, args[j].j);
-                       break;
-
-               case TYPE_FLT:
-                       argument_vmarray_store_flt(array, pd, args[j].j);
-                       break;
-
-               case TYPE_DBL:
-                       argument_vmarray_store_dbl(array, pd, args[j].j);
-                       break;
-
-               case TYPE_ADR: 
-                       argument_vmarray_store_adr(array, pd, (java_handle_t *) args[j].l);
-                       break;
-               }
-       }
-
-       return array;
-}
-
-
-/* argument_vmarray_from_objectarray *******************************************
-
-   Creates an argument array which can be passed to asm_vm_call_method.
-   The array is created from the passed objectarray of boxed values.
-
-   ATTENTION: This function has to be used outside the native world.
-
-   RETURN VALUE:
-      NULL.........indicates an error while creating the array
-      (-1).........no error, but an empty array
-      otherwise....array containing the argument values
-
-*******************************************************************************/
-
-uint64_t *argument_vmarray_from_objectarray(methodinfo *m, java_handle_t *o,
-                                                                                       java_handle_objectarray_t *params)
-{
-       methoddesc    *md;
-       paramdesc     *pd;
-       typedesc      *td;
-       uint64_t      *array;
-       java_handle_t *param;
-       classinfo     *c;
-       int            type;
-       int32_t        i;
-       int32_t        j;
-       imm_union      value;
-
-       /* get the descriptors */
-
-       md = m->parseddesc;
-       pd = md->params;
-       td = md->paramtypes;
-
-       /* allocate argument array */
-
-       array = DMNEW(uint64_t, INT_ARG_CNT + FLT_ARG_CNT + md->memuse);
-
-       /* The array can be NULL if we don't have any arguments to pass
-          and the architecture does not have any argument registers
-          (e.g. i386).  In that case we return (-1) to indicate
-          that no exception should be thrown */
-
-       if (array == NULL)
-               array = (uint64_t *)(-1);
-
-       /* if method is non-static fill first block and skip `this' pointer */
-
-       i = 0;
-
-       if (o != NULL) {
-               /* this pointer */
-               argument_vmarray_store_adr(array, pd, o);
-
-               pd++;
-               td++;
-               i++;
-       }
-
-       for (j = 0; i < md->paramcount; i++, j++, pd++, td++) {
-               /* XXX This function can throw an exception, which should not happend
-                  here, since we are outside the nativeworld. */
-               param = array_objectarray_element_get(params, j);
-
-               switch (td->type) {
-               case TYPE_INT:
-                       if (param == NULL)
-                               return NULL;
-
-                       /* convert the value according to its declared type */
-
-                       LLNI_class_get(param, c);
-                       type = Primitive_get_type_by_wrapperclass(c);
-
-                       switch (td->primitivetype) {
-                       case PRIMITIVETYPE_BOOLEAN:
-                               switch (type) {
-                               case PRIMITIVETYPE_BOOLEAN:
-                                       /* This type is OK. */
-                                       break;
-                               default:
-                                       return NULL;
-                               }
-                               break;
-
-                       case PRIMITIVETYPE_BYTE:
-                               switch (type) {
-                               case PRIMITIVETYPE_BYTE:
-                                       /* This type is OK. */
-                                       break;
-                               default:
-                                       return NULL;
-                               }
-                               break;
-
-                       case PRIMITIVETYPE_CHAR:
-                               switch (type) {
-                               case PRIMITIVETYPE_CHAR:
-                                       /* This type is OK. */
-                                       break;
-                               default:
-                                       return NULL;
-                               }
-                               break;
-
-                       case PRIMITIVETYPE_SHORT:
-                               switch (type) {
-                               case PRIMITIVETYPE_BYTE:
-                               case PRIMITIVETYPE_SHORT:
-                                       /* These types are OK. */
-                                       break;
-                               default:
-                                       return NULL;
-                               }
-                               break;
-
-                       case PRIMITIVETYPE_INT:
-                               switch (type) {
-                               case PRIMITIVETYPE_BYTE:
-                               case PRIMITIVETYPE_SHORT:
-                               case PRIMITIVETYPE_INT:
-                                       /* These types are OK. */
-                                       break;
-                               default:
-                                       return NULL;
-                               }
-                               break;
-
-                       default:
-                               vm_abort("argument_vmarray_from_objectarray: invalid type %d",
-                                                td->primitivetype);
-                       }
-
-                       value = Primitive_unbox(param);
-                       argument_vmarray_store_int(array, pd, value.i);
-                       break;
-
-               case TYPE_LNG:
-                       if (param == NULL)
-                               return NULL;
-
-                       LLNI_class_get(param, c);
-                       type = Primitive_get_type_by_wrapperclass(c);
-
-                       assert(td->primitivetype == PRIMITIVETYPE_LONG);
-
-                       switch (type) {
-                       case PRIMITIVETYPE_BYTE:
-                       case PRIMITIVETYPE_SHORT:
-                       case PRIMITIVETYPE_INT:
-                       case PRIMITIVETYPE_LONG:
-                               /* These types are OK. */
-                               break;
-                       default:
-                               return NULL;
-                       }
-
-                       value = Primitive_unbox(param);
-                       argument_vmarray_store_lng(array, pd, value.l);
-                       break;
-
-               case TYPE_FLT:
-                       if (param == NULL)
-                               return NULL;
-
-                       LLNI_class_get(param, c);
-                       type = Primitive_get_type_by_wrapperclass(c);
-
-                       assert(td->primitivetype == PRIMITIVETYPE_FLOAT);
-
-                       switch (type) {
-                       case PRIMITIVETYPE_FLOAT:
-                               /* This type is OK. */
-                               break;
-                       default:
-                               return NULL;
-                       }
-
-                       value = Primitive_unbox(param);
-                       argument_vmarray_store_flt(array, pd, value.l);
-                       break;
-
-               case TYPE_DBL:
-                       if (param == NULL)
-                               return NULL;
-
-                       LLNI_class_get(param, c);
-                       type = Primitive_get_type_by_wrapperclass(c);
-
-                       assert(td->primitivetype == PRIMITIVETYPE_DOUBLE);
-
-                       switch (type) {
-                       case PRIMITIVETYPE_FLOAT:
-                       case PRIMITIVETYPE_DOUBLE:
-                               /* These types are OK. */
-                               break;
-                       default:
-                               return NULL;
-                       }
-
-                       value = Primitive_unbox(param);
-                       argument_vmarray_store_dbl(array, pd, value.l);
-                       break;
-               
-               case TYPE_ADR:
-                       if (!resolve_class_from_typedesc(td, true, true, &c))
-                               return NULL;
-
-                       if (param != NULL) {
-                               if (td->arraydim > 0) {
-                                       if (!builtin_arrayinstanceof(param, c))
-                                               return NULL;
-                               }
-                               else {
-                                       if (!builtin_instanceof(param, c))
-                                               return NULL;
-                               }
-                       }
-
-                       argument_vmarray_store_adr(array, pd, param);
-                       break;
-
-               default:
-                       vm_abort("argument_vmarray_from_objectarray: invalid type %d", td->type);
-               }
-       }
-
-       return array;
-}
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
diff --git a/src/vm/jit/argument.cpp b/src/vm/jit/argument.cpp
new file mode 100644 (file)
index 0000000..60ddfaf
--- /dev/null
@@ -0,0 +1,769 @@
+/* src/vm/jit/argument.cpp - argument passing from and to JIT methods
+
+   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 "arch.h"
+
+#include "mm/memory.h"
+
+#include "native/llni.h"
+
+#include "vm/array.hpp"
+#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"
+
+
+/* argument_jitarray_load ******************************************************
+   Returns the argument specified by index from one of the passed arrays
+   and returns it.
+
+*******************************************************************************/
+
+imm_union argument_jitarray_load(methoddesc *md, int32_t index,
+                                                                uint64_t *arg_regs, uint64_t *stack)
+{
+       imm_union  ret;
+       paramdesc *pd;
+
+       pd = &md->params[index];
+
+       switch (md->paramtypes[index].type) {
+               case TYPE_INT:
+               case TYPE_ADR:
+                       if (pd->inmemory) {
+#if (SIZEOF_VOID_P == 8)
+                               ret.l = (int64_t)stack[pd->index];
+#else
+                               ret.l = *(int32_t *)(stack + pd->index);
+#endif
+                       } else {
+#if (SIZEOF_VOID_P == 8)
+                               ret.l = arg_regs[index];
+#else
+                               ret.l = *(int32_t *)(arg_regs + index);
+#endif
+                       }
+                       break;
+               case TYPE_LNG:
+                       if (pd->inmemory) {
+                               ret.l = (int64_t)stack[pd->index];
+                       } else {
+                               ret.l = (int64_t)arg_regs[index];
+                       }
+                       break;
+               case TYPE_FLT:
+                       if (pd->inmemory) {
+                               ret.l = (int64_t)stack[pd->index];
+                       } else {
+                               ret.l = (int64_t)arg_regs[index];
+                       }
+                       break;
+               case TYPE_DBL:
+                       if (pd->inmemory) {
+                               ret.l = (int64_t)stack[pd->index];
+                       } else {
+                               ret.l = (int64_t)arg_regs[index];
+                       }
+                       break;
+       }
+
+       return ret;
+}
+
+
+/* argument_jitarray_store *****************************************************
+   Stores the argument into one of the passed arrays at a slot specified
+   by index.
+
+*******************************************************************************/
+
+void argument_jitarray_store(methoddesc *md, int32_t index,
+                                                        uint64_t *arg_regs, uint64_t *stack,
+                                                        imm_union param)
+{
+       paramdesc *pd;
+
+       pd = &md->params[index];
+
+       switch (md->paramtypes[index].type) {
+               case TYPE_ADR:
+                       if (pd->inmemory) {
+#if (SIZEOF_VOID_P == 8)
+                               stack[pd->index] = param.l;
+#else
+                               assert(0);
+#endif
+                       } else {
+                               arg_regs[index] = param.l;
+                       }
+                       break;
+               default:
+                       os::abort("argument_jitarray_store: type not implemented");
+                       break;
+       }
+}
+
+
+/* argument_jitreturn_load *****************************************************
+
+   Loads the proper return value form the return register and returns it.
+
+*******************************************************************************/
+
+imm_union argument_jitreturn_load(methoddesc *md, uint64_t *return_regs)
+{
+       imm_union ret;
+
+       switch (md->returntype.type) {
+               case TYPE_INT:
+               case TYPE_ADR:
+#if (SIZEOF_VOID_P == 8)
+                       ret.l = return_regs[0];
+#else
+                       ret.l = *(int32_t *)return_regs;
+#endif
+                       break;
+               case TYPE_LNG:
+                       ret.l = *(int64_t *)return_regs;
+                       break;
+               case TYPE_FLT:
+                       ret.l = *(int64_t *)return_regs;
+                       break;
+               case TYPE_DBL:
+                       ret.l = *(int64_t *)return_regs;
+                       break;
+       }
+
+       return ret;
+}
+
+
+/* argument_jitreturn_store ****************************************************
+
+   Stores the proper return value into the return registers.
+
+*******************************************************************************/
+
+void argument_jitreturn_store(methoddesc *md, uint64_t *return_regs, imm_union ret)
+{
+       switch (md->returntype.type) {
+               case TYPE_ADR:
+#if (SIZEOF_VOID_P == 8)
+                       return_regs[0] = ret.l;
+#else
+                       assert(0);
+#endif
+                       break;
+               default:
+                       os::abort("argument_jitreturn_store: type not implemented");
+                       break;
+       }
+}
+
+
+/* argument_vmarray_store_int **************************************************
+
+   Helper function to store an integer into the argument array, taking
+   care of architecture specific issues.
+
+*******************************************************************************/
+
+static void argument_vmarray_store_int(uint64_t *array, paramdesc *pd, int32_t value)
+{
+       int32_t index;
+
+       if (!pd->inmemory) {
+               index        = pd->index;
+               array[index] = (int64_t) value;
+       }
+       else {
+               index        = ARG_CNT + pd->index;
+#if SIZEOF_VOID_P == 8
+               array[index] = (int64_t) value;
+#else
+# if WORDS_BIGENDIAN == 1
+               array[index] = ((int64_t) value) << 32;
+# else
+               array[index] = (int64_t) value;
+# endif
+#endif
+       }
+}
+
+
+/* argument_vmarray_store_lng **************************************************
+
+   Helper function to store a long into the argument array, taking
+   care of architecture specific issues.
+
+*******************************************************************************/
+
+static void argument_vmarray_store_lng(uint64_t *array, paramdesc *pd, int64_t value)
+{
+       int32_t index;
+
+#if SIZEOF_VOID_P == 8
+       if (!pd->inmemory)
+               index = pd->index;
+       else
+               index = ARG_CNT + pd->index;
+
+       array[index] = value;
+#else
+       if (!pd->inmemory) {
+               /* move low and high 32-bits into it's own argument slot */
+
+               index        = GET_LOW_REG(pd->index);
+               array[index] = value & 0x00000000ffffffff;
+
+               index        = GET_HIGH_REG(pd->index);
+               array[index] = value >> 32;
+       }
+       else {
+               index        = ARG_CNT + pd->index;
+               array[index] = value;
+       }
+#endif
+}
+
+
+/* argument_vmarray_store_flt **************************************************
+
+   Helper function to store a float into the argument array, taking
+   care of architecture specific issues.
+
+*******************************************************************************/
+
+static void argument_vmarray_store_flt(uint64_t *array, paramdesc *pd, uint64_t value)
+{
+       int32_t index;
+
+       if (!pd->inmemory) {
+#if defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS)
+               index        = pd->index;
+#else
+               index        = INT_ARG_CNT + pd->index;
+#endif
+#if WORDS_BIGENDIAN == 1 && !defined(__POWERPC__) && !defined(__POWERPC64__) && !defined(__S390__)
+               array[index] = value >> 32;
+#else
+               array[index] = value;
+#endif
+       }
+       else {
+               index        = ARG_CNT + pd->index;
+#if defined(__SPARC_64__)
+               array[index] = value >> 32;
+#else
+               array[index] = value;
+#endif
+       }
+}
+
+
+/* argument_vmarray_store_dbl **************************************************
+
+   Helper function to store a double into the argument array, taking
+   care of architecture specific issues.
+
+*******************************************************************************/
+
+static void argument_vmarray_store_dbl(uint64_t *array, paramdesc *pd, uint64_t value)
+{
+       int32_t index;
+
+       if (!pd->inmemory) {
+#if SIZEOF_VOID_P != 8 && defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS)
+               index        = GET_LOW_REG(pd->index);
+               array[index] = value & 0x00000000ffffffff;
+
+               index        = GET_HIGH_REG(pd->index);
+               array[index] = value >> 32;
+#else
+               index        = INT_ARG_CNT + pd->index;
+               array[index] = value;
+#endif
+       }
+       else {
+               index        = ARG_CNT + pd->index;
+               array[index] = value;
+       }
+}
+
+
+/* argument_vmarray_store_adr **************************************************
+
+   Helper function to store an address into the argument array, taking
+   care of architecture specific issues.
+
+   ATTENTION: This function has to be used outside the nativeworld.
+
+*******************************************************************************/
+
+static void argument_vmarray_store_adr(uint64_t *array, paramdesc *pd, java_handle_t *h)
+{
+       void    *value;
+       int32_t  index;
+
+       /* Take the reference value out of the handle. */
+
+       value = LLNI_UNWRAP(h);
+
+       if (!pd->inmemory) {
+#if defined(HAS_ADDRESS_REGISTER_FILE)
+               /* When the architecture has address registers, place them
+                  after integer and float registers. */
+
+               index        = INT_ARG_CNT + FLT_ARG_CNT + pd->index;
+#else
+               index        = pd->index;
+#endif
+               array[index] = (uint64_t) (intptr_t) value;
+       }
+       else {
+               index        = ARG_CNT + pd->index;
+#if SIZEOF_VOID_P == 8
+               array[index] = (uint64_t) (intptr_t) value;
+#else
+# if WORDS_BIGENDIAN == 1
+               array[index] = ((uint64_t) (intptr_t) value) << 32;
+# else
+               array[index] = (uint64_t) (intptr_t) value;
+# endif
+#endif
+       }
+}
+
+
+/* argument_vmarray_from_valist ************************************************
+
+   Creates an argument array which can be passed to asm_vm_call_method.
+   The array is created from the passed valist.
+
+   ATTENTION: This function has to be used outside the native world.
+
+*******************************************************************************/
+
+uint64_t *argument_vmarray_from_valist(methodinfo *m, java_handle_t *o, va_list ap)
+{
+       methoddesc *md;
+       paramdesc  *pd;
+       typedesc   *td;
+       uint64_t   *array;
+       int32_t     i;
+       imm_union   value;
+
+       /* get the descriptors */
+
+       md = m->parseddesc;
+       pd = md->params;
+       td = md->paramtypes;
+
+       // Allocate argument array.
+       array = (uint64_t*) DumpMemory::allocate(sizeof(uint64_t) * (INT_ARG_CNT + FLT_ARG_CNT + md->memuse));
+
+       /* if method is non-static fill first block and skip `this' pointer */
+
+       i = 0;
+
+       if (o != NULL) {
+               /* the `this' pointer */
+               argument_vmarray_store_adr(array, pd, o);
+
+               pd++;
+               td++;
+               i++;
+       } 
+
+       for (; i < md->paramcount; i++, pd++, td++) {
+               switch (td->type) {
+               case TYPE_INT:
+                       value.i = va_arg(ap, int32_t);
+                       argument_vmarray_store_int(array, pd, value.i);
+                       break;
+
+               case TYPE_LNG:
+                       value.l = va_arg(ap, int64_t);
+                       argument_vmarray_store_lng(array, pd, value.l);
+                       break;
+
+               case TYPE_FLT:
+#if defined(__ALPHA__) || defined(__POWERPC__) || defined(__POWERPC64__)
+                       /* This is required to load the correct float value in
+                          assembler code. */
+
+                       value.d = (double) va_arg(ap, double);
+#else
+                       value.f = (float) va_arg(ap, double);
+#endif
+                       argument_vmarray_store_flt(array, pd, value.l);
+                       break;
+
+               case TYPE_DBL:
+                       value.d = va_arg(ap, double);
+                       argument_vmarray_store_dbl(array, pd, value.l);
+                       break;
+
+               case TYPE_ADR: 
+                       value.a = va_arg(ap, void*);
+                       argument_vmarray_store_adr(array, pd, static_cast<java_handle_t*>(value.a));
+                       break;
+               }
+       }
+
+       return array;
+}
+
+
+/* argument_vmarray_from_jvalue ************************************************
+
+   Creates an argument array which can be passed to asm_vm_call_method.
+   The array is created from the passed jvalue array.
+
+   ATTENTION: This function has to be used outside the native world.
+
+*******************************************************************************/
+
+uint64_t *argument_vmarray_from_jvalue(methodinfo *m, java_handle_t *o,
+                                                                          const jvalue *args)
+{
+       methoddesc *md;
+       paramdesc  *pd;
+       typedesc   *td;
+       uint64_t   *array;
+       int32_t     i;
+       int32_t     j;
+
+       /* get the descriptors */
+
+       md = m->parseddesc;
+       pd = md->params;
+       td = md->paramtypes;
+
+       /* allocate argument array */
+
+#if defined(HAS_ADDRESS_REGISTER_FILE)
+       array = (uint64_t*) DumpMemory::allocate(sizeof(uint64_t) * (INT_ARG_CNT + FLT_ARG_CNT + ADR_ARG_CNT + md->memuse));
+#else
+       array = (uint64_t*) DumpMemory::allocate(sizeof(uint64_t) * (INT_ARG_CNT + FLT_ARG_CNT + md->memuse));
+#endif
+
+       /* if method is non-static fill first block and skip `this' pointer */
+
+       i = 0;
+
+       if (o != NULL) {
+               /* the `this' pointer */
+               argument_vmarray_store_adr(array, pd, o);
+
+               pd++;
+               td++;
+               i++;
+       } 
+
+       for (j = 0; i < md->paramcount; i++, j++, pd++, td++) {
+               switch (td->primitivetype) {
+               case TYPE_INT:
+                       argument_vmarray_store_int(array, pd, args[j].i);
+                       break;
+
+               case TYPE_LNG:
+                       argument_vmarray_store_lng(array, pd, args[j].j);
+                       break;
+
+               case TYPE_FLT:
+                       argument_vmarray_store_flt(array, pd, args[j].j);
+                       break;
+
+               case TYPE_DBL:
+                       argument_vmarray_store_dbl(array, pd, args[j].j);
+                       break;
+
+               case TYPE_ADR: 
+                       argument_vmarray_store_adr(array, pd, (java_handle_t *) args[j].l);
+                       break;
+               }
+       }
+
+       return array;
+}
+
+
+/* argument_vmarray_from_objectarray *******************************************
+
+   Creates an argument array which can be passed to asm_vm_call_method.
+   The array is created from the passed objectarray of boxed values.
+
+   ATTENTION: This function has to be used outside the native world.
+
+   RETURN VALUE:
+      NULL.........indicates an error while creating the array
+      (-1).........no error, but an empty array
+      otherwise....array containing the argument values
+
+*******************************************************************************/
+
+uint64_t *argument_vmarray_from_objectarray(methodinfo *m, java_handle_t *o,
+                                                                                       java_handle_objectarray_t *params)
+{
+       methoddesc    *md;
+       paramdesc     *pd;
+       typedesc      *td;
+       uint64_t      *array;
+       java_handle_t *param;
+       classinfo     *c;
+       int            type;
+       int32_t        i;
+       int32_t        j;
+       imm_union      value;
+
+       /* get the descriptors */
+
+       md = m->parseddesc;
+       pd = md->params;
+       td = md->paramtypes;
+
+       /* allocate argument array */
+
+       array = (uint64_t*) DumpMemory::allocate(sizeof(uint64_t) * (INT_ARG_CNT + FLT_ARG_CNT + md->memuse));
+
+       /* The array can be NULL if we don't have any arguments to pass
+          and the architecture does not have any argument registers
+          (e.g. i386).  In that case we return (-1) to indicate
+          that no exception should be thrown */
+
+       if (array == NULL)
+               array = (uint64_t *)(-1);
+
+       /* if method is non-static fill first block and skip `this' pointer */
+
+       i = 0;
+
+       if (o != NULL) {
+               /* this pointer */
+               argument_vmarray_store_adr(array, pd, o);
+
+               pd++;
+               td++;
+               i++;
+       }
+
+       for (j = 0; i < md->paramcount; i++, j++, pd++, td++) {
+               /* XXX This function can throw an exception, which should not happend
+                  here, since we are outside the nativeworld. */
+               param = array_objectarray_element_get(params, j);
+
+               switch (td->type) {
+               case TYPE_INT:
+                       if (param == NULL)
+                               return NULL;
+
+                       /* convert the value according to its declared type */
+
+                       LLNI_class_get(param, c);
+                       type = Primitive::get_type_by_wrapperclass(c);
+
+                       switch (td->primitivetype) {
+                       case PRIMITIVETYPE_BOOLEAN:
+                               switch (type) {
+                               case PRIMITIVETYPE_BOOLEAN:
+                                       /* This type is OK. */
+                                       break;
+                               default:
+                                       return NULL;
+                               }
+                               break;
+
+                       case PRIMITIVETYPE_BYTE:
+                               switch (type) {
+                               case PRIMITIVETYPE_BYTE:
+                                       /* This type is OK. */
+                                       break;
+                               default:
+                                       return NULL;
+                               }
+                               break;
+
+                       case PRIMITIVETYPE_CHAR:
+                               switch (type) {
+                               case PRIMITIVETYPE_CHAR:
+                                       /* This type is OK. */
+                                       break;
+                               default:
+                                       return NULL;
+                               }
+                               break;
+
+                       case PRIMITIVETYPE_SHORT:
+                               switch (type) {
+                               case PRIMITIVETYPE_BYTE:
+                               case PRIMITIVETYPE_SHORT:
+                                       /* These types are OK. */
+                                       break;
+                               default:
+                                       return NULL;
+                               }
+                               break;
+
+                       case PRIMITIVETYPE_INT:
+                               switch (type) {
+                               case PRIMITIVETYPE_BYTE:
+                               case PRIMITIVETYPE_SHORT:
+                               case PRIMITIVETYPE_INT:
+                                       /* These types are OK. */
+                                       break;
+                               default:
+                                       return NULL;
+                               }
+                               break;
+
+                       default:
+                               os::abort("argument_vmarray_from_objectarray: invalid type %d",
+                                                td->primitivetype);
+                       }
+
+                       value = Primitive::unbox(param);
+                       argument_vmarray_store_int(array, pd, value.i);
+                       break;
+
+               case TYPE_LNG:
+                       if (param == NULL)
+                               return NULL;
+
+                       LLNI_class_get(param, c);
+                       type = Primitive::get_type_by_wrapperclass(c);
+
+                       assert(td->primitivetype == PRIMITIVETYPE_LONG);
+
+                       switch (type) {
+                       case PRIMITIVETYPE_BYTE:
+                       case PRIMITIVETYPE_SHORT:
+                       case PRIMITIVETYPE_INT:
+                       case PRIMITIVETYPE_LONG:
+                               /* These types are OK. */
+                               break;
+                       default:
+                               return NULL;
+                       }
+
+                       value = Primitive::unbox(param);
+                       argument_vmarray_store_lng(array, pd, value.l);
+                       break;
+
+               case TYPE_FLT:
+                       if (param == NULL)
+                               return NULL;
+
+                       LLNI_class_get(param, c);
+                       type = Primitive::get_type_by_wrapperclass(c);
+
+                       assert(td->primitivetype == PRIMITIVETYPE_FLOAT);
+
+                       switch (type) {
+                       case PRIMITIVETYPE_FLOAT:
+                               /* This type is OK. */
+                               break;
+                       default:
+                               return NULL;
+                       }
+
+                       value = Primitive::unbox(param);
+                       argument_vmarray_store_flt(array, pd, value.l);
+                       break;
+
+               case TYPE_DBL:
+                       if (param == NULL)
+                               return NULL;
+
+                       LLNI_class_get(param, c);
+                       type = Primitive::get_type_by_wrapperclass(c);
+
+                       assert(td->primitivetype == PRIMITIVETYPE_DOUBLE);
+
+                       switch (type) {
+                       case PRIMITIVETYPE_FLOAT:
+                       case PRIMITIVETYPE_DOUBLE:
+                               /* These types are OK. */
+                               break;
+                       default:
+                               return NULL;
+                       }
+
+                       value = Primitive::unbox(param);
+                       argument_vmarray_store_dbl(array, pd, value.l);
+                       break;
+               
+               case TYPE_ADR:
+                       if (!resolve_class_from_typedesc(td, true, true, &c))
+                               return NULL;
+
+                       if (param != NULL) {
+                               if (td->arraydim > 0) {
+                                       if (!builtin_arrayinstanceof(param, c))
+                                               return NULL;
+                               }
+                               else {
+                                       if (!builtin_instanceof(param, c))
+                                               return NULL;
+                               }
+                       }
+
+                       argument_vmarray_store_adr(array, pd, param);
+                       break;
+
+               default:
+                       os::abort("argument_vmarray_from_objectarray: invalid type %d", td->type);
+               }
+       }
+
+       return array;
+}
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
diff --git a/src/vm/jit/argument.h b/src/vm/jit/argument.h
deleted file mode 100644 (file)
index fe6ef25..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-/* src/vm/jit/argument.h - argument passing from and to JIT methods
-
-   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 _VM_JIT_ARGUMENT_H
-#define _VM_JIT_ARGUMENT_H
-
-#include "config.h"
-
-#include <stdint.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "vm/global.h"
-
-
-/* function prototypes ********************************************************/
-
-imm_union argument_jitarray_load(methoddesc *md, int32_t index,
-                                                                uint64_t *arg_regs, uint64_t *stack);
-void      argument_jitarray_store(methoddesc *md, int32_t index,
-                                                                 uint64_t *arg_regs, uint64_t *stack,
-                                                                 imm_union param);
-
-imm_union argument_jitreturn_load(methoddesc *md, uint64_t *return_regs);
-void      argument_jitreturn_store(methoddesc *md, uint64_t *return_regs,
-                                                                  imm_union ret);
-
-uint64_t *argument_vmarray_from_valist(methodinfo *m, java_handle_t *o,
-                                                                          va_list ap);
-uint64_t *argument_vmarray_from_jvalue(methodinfo *m, java_handle_t *o,
-                                                                          const jvalue *args);
-uint64_t *argument_vmarray_from_objectarray(methodinfo *m, java_handle_t *o,
-                                                                                       java_handle_objectarray_t *params);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _VM_JIT_ARGUMENT_H */
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
diff --git a/src/vm/jit/argument.hpp b/src/vm/jit/argument.hpp
new file mode 100644 (file)
index 0000000..07ca62d
--- /dev/null
@@ -0,0 +1,71 @@
+/* src/vm/jit/argument.hpp - argument passing from and to JIT methods
+
+   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 _VM_JIT_ARGUMENT_HPP
+#define _VM_JIT_ARGUMENT_HPP
+
+#include "config.h"
+
+#include <stdint.h>
+
+#include "vm/global.h"
+#include "vm/method.h"
+
+
+/* function prototypes ********************************************************/
+
+imm_union argument_jitarray_load(methoddesc *md, int32_t index,
+                                                                uint64_t *arg_regs, uint64_t *stack);
+void      argument_jitarray_store(methoddesc *md, int32_t index,
+                                                                 uint64_t *arg_regs, uint64_t *stack,
+                                                                 imm_union param);
+
+imm_union argument_jitreturn_load(methoddesc *md, uint64_t *return_regs);
+void      argument_jitreturn_store(methoddesc *md, uint64_t *return_regs,
+                                                                  imm_union ret);
+
+uint64_t *argument_vmarray_from_valist(methodinfo *m, java_handle_t *o,
+                                                                          va_list ap);
+uint64_t *argument_vmarray_from_jvalue(methodinfo *m, java_handle_t *o,
+                                                                          const jvalue *args);
+uint64_t *argument_vmarray_from_objectarray(methodinfo *m, java_handle_t *o,
+                                                                                       java_handle_objectarray_t *params);
+
+#endif // _VM_JIT_ARGUMENT_HPP
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
index de85844084064d535b394a210a82840bea7d23be..169c28ad96a410880f0a75c72e3acb86503b2580 100644 (file)
@@ -51,6 +51,7 @@ libarch_la_SOURCES = \
        \
        md-abi.c \
        md-abi.h \
+       md-stubs.hpp \
        md-trap.h \
        md.c \
        md.h
index a1175a355be9e7d26b6ff0eca08f7396311a97ea..b8bdeeb82146e6a32689ff012a7283426abb3067 100644 (file)
 #ifndef _ARCH_H
 #define _ARCH_H
 
+#define JIT_COMPILER_VIA_SIGNAL
+
 #include "config.h"
 
 
 /* define architecture features ***********************************************/
 
-#define U8_AVAILABLE                     1
-
 #define SUPPORT_DIVISION                 0
 #define SUPPORT_LONG                     1
 
index d3f4b93fdddcc5802cb94e47dfe1b484b5dd327c..7786ab160be30e6a4ba9b07f8fa39a69393557a7 100644 (file)
@@ -47,8 +47,6 @@
        .globl asm_vm_call_method_exception_handler
        .globl asm_vm_call_method_end
 
-       .globl asm_call_jit_compiler
-
        .globl asm_handle_exception
        .globl asm_handle_nat_exception
 
@@ -137,56 +135,6 @@ asm_vm_call_method_exception_handler:
 asm_vm_call_method_end:
 
 
-/****************** function asm_call_jit_compiler *****************************
-*                                                                              *
-*   Invokes the compiler for untranslated JavaVM methods.                      *
-*   What this method does:                                                     *
-*    - save args and LR                                                        *
-*    - fire up jit_compile (pass methodinfo pointer)                           *
-*    - try to find out where to write back the new method pointer              *
-*    - restore args and LR                                                     *
-*    - check for exceptions                                                    *
-*    - eventually write back new method pointer                                *
-*    - call jit code (wich will then return to caller)                         *
-*                                                                              *
-*   These methods can call us: codegen_compilerstub & asm_calljavafunction     *
-*   ATTENTION: use REG_ITMP1 to pass methodinfo pointer to me!                 *
-*                                                                              *
-*******************************************************************************/
-
-#define MYSTACKSIZE (6*4)
-
-asm_call_jit_compiler:
-       SAVE_ARGUMENT_REGISTERS             /* save our argument registers & LR   */
-       sub   sp, sp, #4                    /* keep stack 8-byte aligned          */
-
-       mov   a0, itmp1                     /* pass methodinfo pointer            */
-       mov   a1, mptr                      /* pass method pointer                */
-       add   a2, sp, #MYSTACKSIZE          /* pass Java sp                       */
-       mov   a3, lr                        /* pass Java RA (correct for leafs)   */
-       bl    jit_asm_compile
-       mov   itmp1, res1                   /* save pointer to new jit-code       */
-
-       tst   itmp1,itmp1                   /* check for exeption                 */
-       beq   L_asm_call_jit_compiler_exception
-
-       add   sp, sp, #4                    /* keep stack 8-byte aligned          */
-       RESTORE_ARGUMENT_REGISTERS          /* load our argument registers & LR   */
-
-       mov   ip, itmp1
-       mov   pc, ip                        /* call jit-code                      */
-
-L_asm_call_jit_compiler_exception:
-       bl    exceptions_get_and_clear_exception
-       mov   xptr, res1                    /* get exception                      */
-
-       add   sp, sp, #4                    /* keep stack 8-byte aligned          */
-       RESTORE_ARGUMENT_REGISTERS          /* load LR                            */
-
-       sub   xpc, lr, #4                   /* xpc = instruction that called us   */
-       b     asm_handle_nat_exception
-
-
 /********************* function asm_handle_exception ***************************
 *                                                                              *
 *   This function handles an exception. It does not use the usual calling      *
index c62b078f730dcf2be55dc1496c0a60e6e6123c9c..efe6d3d746eac7d775dae8bc56eb9495294cb972 100644 (file)
 
 #include "mm/memory.h"
 
-#include "native/localref.h"
-#include "native/native.h"
+#include "native/localref.hpp"
+#include "native/native.hpp"
 
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/exceptions.hpp"
 #include "vm/global.h"
-#include "vm/loader.h"
+#include "vm/loader.hpp"
 #include "vm/options.h"
 #include "vm/vm.hpp"
 
 #include "vm/jit/abi.h"
 #include "vm/jit/asmpart.h"
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/codegen-common.hpp"
 #include "vm/jit/dseg.h"
-#include "vm/jit/emit-common.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/emit-common.hpp"
+#include "vm/jit/jit.hpp"
 #include "vm/jit/jitcache.hpp"
-#include "vm/jit/linenumbertable.h"
+#include "vm/jit/linenumbertable.hpp"
 #include "vm/jit/methodheader.h"
 #include "vm/jit/parse.h"
-#include "vm/jit/patcher-common.h"
+#include "vm/jit/patcher-common.hpp"
 #include "vm/jit/reg.h"
 
 #if defined(ENABLE_LSRA)
@@ -1051,7 +1051,12 @@ bool codegen_emit(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
+#if defined(__VFP_FP__)
+                       M_FMSR(s1, d);
+                       M_CVTIF(d, d);
+#else
                        M_CVTIF(s1, d);
+#endif
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -1059,7 +1064,12 @@ bool codegen_emit(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
+#if defined(__VFP_FP__)
+                       M_FMSR(s1, d);
+                       M_CVTID(d, d);
+#else
                        M_CVTID(s1, d);
+#endif
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -1067,9 +1077,12 @@ bool codegen_emit(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+#if defined(__VFP_FP__)
+                       M_CVTFI(s1, REG_FTMP2);
+                       M_FMRS(REG_FTMP2, d);
+#else
                        /* this uses round towards zero, as Java likes it */
                        M_CVTFI(s1, d);
-#if !defined(__VFP_FP__)
                        /* this checks for NaN; to return zero as Java likes it */
                        M_FCMP(s1, 0x8);
                        M_MOVVS_IMM(0, d);
@@ -1081,9 +1094,12 @@ bool codegen_emit(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+#if defined(__VFP_FP__)
+                       M_CVTDI(s1, REG_FTMP2);
+                       M_FMRS(REG_FTMP2, d);
+#else
                        /* this uses round towards zero, as Java likes it */
                        M_CVTDI(s1, d);
-#if !defined(__VFP_FP__)
                        /* this checks for NaN; to return zero as Java likes it */
                        M_DCMP(s1, 0x8);
                        M_MOVVS_IMM(0, d);
@@ -2884,29 +2900,6 @@ bool codegen_emit(jitdata *jd)
 }
 
 
-/* codegen_emit_stub_compiler **************************************************
-
-   Emits a stub routine which calls the compiler.
-       
-*******************************************************************************/
-
-void codegen_emit_stub_compiler(jitdata *jd)
-{
-       methodinfo  *m;
-       codegendata *cd;
-
-       /* get required compiler data */
-
-       m  = jd->m;
-       cd = jd->cd;
-
-       /* code for the stub */
-
-       M_LDR_INTERN(REG_ITMP1, REG_PC, -(2 * 4 + 2 * SIZEOF_VOID_P));
-       M_LDR_INTERN(REG_PC, REG_PC, -(3 * 4 + 3 * SIZEOF_VOID_P));
-}
-
-
 /* codegen_emit_stub_native ****************************************************
 
    Emits a stub routine which calls a native method.
index fc7dee7e3af79d52e7dba065e6ef728e7e374883..b57d26cb229286f0579dfb68d3ef4954699715c5 100644 (file)
@@ -1,9 +1,7 @@
 /* src/vm/jit/arm/codegen.h - code generation macros and definitions for ARM
 
-   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
-   C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
-   E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
-   J. Wenninger, Institut f. Computersprachen - TU Wien
+   Copyright (C) 1996-2005, 2006, 2007, 2008
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
 
     } while (0)
 
 
-/* stub defines ***************************************************************/
-
-#define COMPILERSTUB_CODESIZE    2 * 4
-
-
 /* lazy debugger **************************************************************/
 
 #if !defined(NDEBUG)
@@ -650,6 +643,7 @@ void asm_debug_intern(int a1, int a2, int a3, int a4);
 #if !defined(ENABLE_SOFTFLOAT)
 
 #if defined(__VFP_FP__)
+
 #define M_FADD(a,b,d)      M_CPDP(UNCOND,0,1,1,0,10,0,0,0,d,a,b)/* d = a +  b */
 #define M_FSUB(a,b,d)      M_CPDP(UNCOND,0,1,1,1,10,0,0,0,d,a,b)/* d = a -  b */
 #define M_FMUL(a,b,d)      M_CPDP(UNCOND,0,1,0,0,10,0,0,0,d,a,b)/* d = a *  b */
@@ -671,8 +665,8 @@ void asm_debug_intern(int a1, int a2, int a3, int a4);
 #define M_CVTFD(a,d)       M_CPDP(UNCOND,1,1,1,1,10,0,1,0,d,0x7,a)
 #define M_CVTIF(a,d)       M_CPDP(UNCOND,1,1,1,1,10,0,1,0,d,0x8,a)
 #define M_CVTID(a,d)       M_CPDP(UNCOND,1,1,1,1,11,0,1,0,d,0x8,a)
-#define M_CVTFI(a,d)       M_CPDP(UNCOND,1,1,1,1,10,0,1,0,d,0xc,a)
-#define M_CVTDI(a,d)       M_CPDP(UNCOND,1,1,1,1,11,0,1,0,d,0xc,a)
+#define M_CVTFI(a,d)       M_CPDP(UNCOND,1,1,1,1,10,0,1,0,d,0xd,a) // ftosis
+#define M_CVTDI(a,d)       M_CPDP(UNCOND,1,1,1,1,11,0,1,0,d,0xd,a) // ftosid
 
 #define M_FMSTAT           M_CPRT(UNCOND,0x07,1,10,0,0x1,0xf)
 
@@ -682,7 +676,9 @@ void asm_debug_intern(int a1, int a2, int a3, int a4);
 #define M_FMRDL(Fa,b)      M_CPRT(UNCOND,0x00,1,11,0,Fa,b)
 #define M_FMDHR(a,Fb)      M_CPRT(UNCOND,0x01,0,11,0,Fb,a)
 #define M_FMRDH(Fa,b)      M_CPRT(UNCOND,0x01,1,11,0,Fa,b)
+
 #else
+
 #define M_FADD(a,b,d)      M_CPDOS(UNCOND,0x00,0,d,a,b)         /* d = a +  b */
 #define M_FSUB(a,b,d)      M_CPDOS(UNCOND,0x02,0,d,a,b)         /* d = a -  b */
 #define M_FMUL(a,b,d)      M_CPDOS(UNCOND,0x01,0,d,a,b)         /* d = a *  b */
@@ -708,6 +704,7 @@ void asm_debug_intern(int a1, int a2, int a3, int a4);
 #define M_CVTID(a,d)       M_CPRTD(UNCOND,0,a,d,0)              /* d = (float) a */
 #define M_CVTFI(a,d)       M_CPRTI(UNCOND,1,d,0,a)              /* d = (int)   a */
 #define M_CVTDI(a,d)       M_CPRTI(UNCOND,1,d,0,a)              /* d = (int)   a */
+
 #endif
 
 
@@ -1103,15 +1100,22 @@ do { \
 /* M_RECOMPUTE_PV:
    used to recompute our PV (we use the IP for this) out of the current PC
    ATTENTION: if you change this, you have to look at other functions as well!
-   Following things depend on it: asm_call_jit_compiler(); codegen_findmethod();
+   Following things depend on it: md_codegen_get_pv_from_pc();
 */
 #define M_RECOMPUTE_PV(disp) \
        disp += 8; /* we use PC relative addr.  */ \
        assert((disp & 0x03) == 0); \
        assert(disp >= 0 && disp <= 0x03ffffff); \
-       M_SUB_IMM(REG_PV, REG_PC, IMM_ROTL(disp >> 2, 1)); \
-       if (disp > 0x000003ff) M_SUB_IMM(REG_PV, REG_PV, IMM_ROTL(disp >> 10, 5)); \
-       if (disp > 0x0003ffff) M_SUB_IMM(REG_PV, REG_PV, IMM_ROTL(disp >> 18, 9)); \
+       if (disp > 0x0003ffff) { \
+               M_SUB_IMM(REG_PV, REG_PC, IMM_ROTL(disp >> 18, 9)); \
+               M_SUB_IMM(REG_PV, REG_PV, IMM_ROTL(disp >> 10, 5)); \
+               M_SUB_IMM(REG_PV, REG_PV, IMM_ROTL(disp >> 2, 1)); \
+       } else if (disp > 0x000003ff) { \
+               M_SUB_IMM(REG_PV, REG_PC, IMM_ROTL(disp >> 10, 5)); \
+               M_SUB_IMM(REG_PV, REG_PV, IMM_ROTL(disp >> 2, 1)); \
+       } else { \
+               M_SUB_IMM(REG_PV, REG_PC, IMM_ROTL(disp >> 2, 1)); \
+       }
 
 /* M_INTMOVE:
    generates an integer-move from register a to b.
index f27c558dfc61e2bbbe2386c1570b50389054249f..a30de77364a166ce0da50c490da268a9341e4e6c 100644 (file)
 
 #include "mm/memory.h"
 
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
 
 #include "vm/global.h"
 
 #include "vm/jit/abi.h"
 #include "vm/jit/asmpart.h"
-#include "vm/jit/emit-common.h"
-#include "vm/jit/jit.h"
-#include "vm/jit/patcher-common.h"
-#include "vm/jit/replace.h"
+#include "vm/jit/emit-common.hpp"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/patcher-common.hpp"
+#include "vm/jit/replace.hpp"
 #include "vm/jit/trace.hpp"
 #include "vm/jit/trap.h"
 
@@ -573,6 +573,18 @@ void emit_exception_check(codegendata *cd, instruction *iptr)
 }
 
 
+/* emit_trap_compiler **********************************************************
+
+   Emit a trap instruction which calls the JIT compiler.
+
+*******************************************************************************/
+
+void emit_trap_compiler(codegendata *cd)
+{
+       M_TRAP(REG_METHODPTR, TRAP_COMPILER);
+}
+
+
 /* emit_trap *******************************************************************
 
    Emit a trap instruction and return the original machine code.
index 191605bb7bb79a3f34ba71e57bd8c48c7745a919..1b1142e5a39b7f94a3f30881bfc6f5b182c8d5d8 100644 (file)
@@ -2,6 +2,7 @@
 
    Copyright (C) 1996-2005, 2006, 2007, 2008
    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+   Copyright (C) 2008 Theobroma Systems Ltd.
 
    This file is part of CACAO.
 
 
 #include <stdint.h>
 
-#include "vm/types.h"
-
-#include "vm/jit/disass.h"
-
-#include "vm/jit/arm/md-abi.h"
-
 #define ucontext broken_glibc_ucontext
 #define ucontext_t broken_glibc_ucontext_t
 #include <ucontext.h>
@@ -49,6 +44,11 @@ typedef struct ucontext {
 
 #define scontext_t struct sigcontext
 
+#include "vm/types.h"
+
+#include "vm/jit/arm/md.h"
+#include "vm/jit/arm/md-abi.h"
+
 #include "threads/thread.hpp"
 
 #include "vm/os.hpp"
@@ -56,7 +56,9 @@ typedef struct ucontext {
 #include "vm/vm.hpp"
 
 #include "vm/jit/asmpart.h"
+#include "vm/jit/disass.h"
 #include "vm/jit/executionstate.h"
+#include "vm/jit/patcher-common.hpp"
 #include "vm/jit/trap.h"
 
 
@@ -78,7 +80,6 @@ void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
        intptr_t        addr;
        int             type;
        intptr_t        val;
-       void           *p;
 
        _uc = (ucontext_t*) _p;
        _sc = &_uc->uc_mcontext;
@@ -106,13 +107,7 @@ void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
 
        /* Handle the trap. */
 
-       p = trap_handle(type, val, pv, sp, ra, xpc, _p);
-
-       /* set registers */
-
-       _sc->arm_r10 = (uintptr_t) p;
-       _sc->arm_fp  = (uintptr_t) xpc;
-       _sc->arm_pc  = (uintptr_t) asm_handle_exception;
+       trap_handle(type, val, pv, sp, ra, xpc, _p);
 }
 
 
@@ -124,57 +119,50 @@ void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
 
 void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p)
 {
-       ucontext_t     *_uc;
-       scontext_t     *_sc;
-       u1             *pv;
-       u1             *sp;
-       u1             *ra;
-       u1             *xpc;
-       u4              mcode;
-       int             type;
-       intptr_t        val;
-       void           *p;
-
-       _uc = (ucontext_t*) _p;
-       _sc = &_uc->uc_mcontext;
+       ucontext_t* _uc = (ucontext_t*) _p;
+       scontext_t* _sc = &_uc->uc_mcontext;
 
        /* ATTENTION: glibc included messed up kernel headers we needed a
           workaround for the ucontext structure. */
 
-       pv  = (u1 *) _sc->arm_ip;
-       sp  = (u1 *) _sc->arm_sp;
-       ra  = (u1 *) _sc->arm_lr;                    /* this is correct for leafs */
-       xpc = (u1 *) _sc->arm_pc;
-
-       /* get exception-throwing instruction */
-
-       mcode = *((u4 *) xpc);
-
-       /* check for undefined instruction we use */
-
-       if ((mcode & 0x0ff000f0) != 0x07f000f0) {
-               log_println("md_signal_handler_sigill: unknown illegal instruction: inst=%x", mcode);
+       void* pv  = (void*) _sc->arm_ip;
+       void* sp  = (void*) _sc->arm_sp;
+       void* ra  = (void*) _sc->arm_lr; // The RA is correct for leaf methods.
+       void* xpc = (void*) _sc->arm_pc;
+
+       // Get the exception-throwing instruction.
+       uint32_t mcode = *((uint32_t*) xpc);
+
+       // Check if the trap instruction is valid.
+       // TODO Move this into patcher_handler.
+       if (patcher_is_valid_trap_instruction_at(xpc) == false) {
+               // Check if the PC has been patched during our way to this
+               // signal handler (see PR85).
+               // NOTE: ARM uses SIGILL for other traps too, but it's OK to
+               // do this check anyway because it will fail.
+               if (patcher_is_patched_at(xpc) == true)
+                       return;
+
+               // We have a problem...
+               log_println("md_signal_handler_sigill: Unknown illegal instruction 0x%x at 0x%x", mcode, xpc);
 #if defined(ENABLE_DISASSEMBLER)
-               DISASSINSTR(xpc);
+               (void) disassinstr(xpc);
 #endif
                vm_abort("Aborting...");
        }
 
-       type = (mcode >> 8) & 0x0fff;
-       val  = *((s4 *) _sc + OFFSET(scontext_t, arm_r0)/4 + (mcode & 0x0f));
-
-       /* Handle the trap. */
-
-       p = trap_handle(type, val, pv, sp, ra, xpc, _p);
+       int      type = (mcode >> 8) & 0x0fff;
+       intptr_t val  = *((int32_t*) _sc + OFFSET(scontext_t, arm_r0)/4 + (mcode & 0x0f));
 
-       /* set registers if we have an exception, continue execution
-          otherwise (this is needed for patchers to work) */
+       if (type == TRAP_COMPILER) {
+               /* The XPC is the RA minus 4, because the RA points to the
+                  instruction after the call. */
 
-       if (p != NULL) {
-               _sc->arm_r10 = (uintptr_t) p;
-               _sc->arm_fp  = (uintptr_t) xpc;
-               _sc->arm_pc  = (uintptr_t) asm_handle_exception;
+               xpc = (void*) (((uintptr_t) ra) - 4);
        }
+
+       // Handle the trap.
+       trap_handle(type, val, pv, sp, ra, xpc, _p);
 }
 
 
@@ -239,33 +227,32 @@ void md_signal_handler_sigusr2(int sig, siginfo_t *siginfo, void *_p)
  */
 void md_executionstate_read(executionstate_t *es, void *context)
 {
-       vm_abort("md_executionstate_read: IMPLEMENT ME!");
-
-#if 0
        ucontext_t *_uc;
-       mcontext_t *_mc;
+       scontext_t *_sc;
        int         i;
 
        _uc = (ucontext_t *) context;
-       _mc = &_uc->uc_mcontext;
+       _sc = &_uc->uc_mcontext;
+
+       /* ATTENTION: glibc included messed up kernel headers we needed a
+          workaround for the ucontext structure. */
 
        /* read special registers */
-       es->pc = (u1 *) _mc->sc_pc;
-       es->sp = (u1 *) _mc->sc_regs[REG_SP];
-       es->pv = (u1 *) _mc->sc_regs[REG_PV];
-       es->ra = (u1 *) _mc->sc_regs[REG_RA];
+
+       es->pc = (u1 *) _sc->arm_pc;
+       es->sp = (u1 *) _sc->arm_sp;
+       es->pv = (u1 *) _sc->arm_ip;
+       es->ra = (u1 *) _sc->arm_lr;
 
        /* read integer registers */
+
        for (i = 0; i < INT_REG_CNT; i++)
-               es->intregs[i] = _mc->sc_regs[i];
+               es->intregs[i] = *((int32_t*) _sc + OFFSET(scontext_t, arm_r0)/4 + i);
 
        /* read float registers */
-       /* Do not use the assignment operator '=', as the type of
-        * the _mc->sc_fpregs[i] can cause invalid conversions. */
 
-       assert(sizeof(_mc->sc_fpregs) == sizeof(es->fltregs));
-       os_memcpy(&es->fltregs, &_mc->sc_fpregs, sizeof(_mc->sc_fpregs));
-#endif
+       for (i = 0; i < FLT_REG_CNT; i++)
+               es->fltregs[i] = 0xdeadbeefdeadbeefULL;
 }
 
 
@@ -277,33 +264,27 @@ void md_executionstate_read(executionstate_t *es, void *context)
  */
 void md_executionstate_write(executionstate_t *es, void *context)
 {
-       vm_abort("md_executionstate_write: IMPLEMENT ME!");
-
-#if 0
        ucontext_t *_uc;
-       mcontext_t *_mc;
+       scontext_t *_sc;
        int         i;
 
        _uc = (ucontext_t *) context;
-       _mc = &_uc->uc_mcontext;
+       _sc = &_uc->uc_mcontext;
 
-       /* write integer registers */
-       for (i = 0; i < INT_REG_CNT; i++)
-               _mc->sc_regs[i] = es->intregs[i];
+       /* ATTENTION: glibc included messed up kernel headers we needed a
+          workaround for the ucontext structure. */
 
-       /* write float registers */
-       /* Do not use the assignment operator '=', as the type of
-        * the _mc->sc_fpregs[i] can cause invalid conversions. */
+       /* write integer registers */
 
-       assert(sizeof(_mc->sc_fpregs) == sizeof(es->fltregs));
-       os_memcpy(&_mc->sc_fpregs, &es->fltregs, sizeof(_mc->sc_fpregs));
+       for (i = 0; i < INT_REG_CNT; i++)
+               *((int32_t*) _sc + OFFSET(scontext_t, arm_r0)/4 + i) = es->intregs[i];
 
        /* write special registers */
-       _mc->sc_pc           = (ptrint) es->pc;
-       _mc->sc_regs[REG_SP] = (ptrint) es->sp;
-       _mc->sc_regs[REG_PV] = (ptrint) es->pv;
-       _mc->sc_regs[REG_RA] = (ptrint) es->ra;
-#endif
+
+       _sc->arm_pc = (ptrint) es->pc;
+       _sc->arm_sp = (ptrint) es->sp;
+       _sc->arm_ip = (ptrint) es->pv;
+       _sc->arm_lr = (ptrint) es->ra;
 }
 
 
diff --git a/src/vm/jit/arm/md-stubs.hpp b/src/vm/jit/arm/md-stubs.hpp
new file mode 100644 (file)
index 0000000..1fb1147
--- /dev/null
@@ -0,0 +1,56 @@
+/* src/vm/jit/arm/md-stubs.hpp - ARM JIT stubs
+
+   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 _MD_STUBS_HPP
+#define _MD_STUBS_HPP
+
+#include "config.h"
+
+
+/**
+ * Return the code size of a compiler on an ARM architecture.
+ *
+ * @return Code size in bytes.
+ */
+int CompilerStub::get_code_size()
+{
+       return 2 * 4;
+}
+
+#endif // _MD_STUBS_HPP
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
index ba9c1f7ee7823667e7e7ec8fd5eb8f3f9970a186..9ce156470118f432c10e3919b93da57270615ef0 100644 (file)
@@ -34,7 +34,7 @@
 #include "vm/types.h"
 
 #include "vm/jit/asmpart.h"
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/codegen-common.hpp"
 
 
 /* md_stacktrace_get_returnaddress *********************************************
@@ -68,30 +68,38 @@ inline static void* md_codegen_get_pv_from_pc(void* ra)
 {
        uint32_t* pc;
        uintptr_t pv;
-       uint32_t mcode1, mcode2, mcode3;
+       uint32_t mcode;
+       int mcode_idx;
 
        pc = (uint32_t*) ra;
        pv = (uintptr_t) ra;
 
        /* this can either be a RECOMPUTE_IP in JIT code or a fake in asm_calljavafunction */
-       mcode1 = pc[0];
-       if ((mcode1 & 0xffffff00) == 0xe24fcf00 /*sub ip,pc,#__*/)
-               pv -= (uintptr_t) ((mcode1 & 0x000000ff) << 2);
-       else if ((mcode1 & 0xffffff00) == 0xe24fc000 /*sub ip,pc,#__*/)
-               pv -= (uintptr_t) (mcode1 & 0x000000ff);
+       mcode_idx = 0;
+       mcode = pc[0];
+
+       /* if this was shifted by 18 bits, we have to load additional instructions */
+       if ((mcode & 0xfff0ff00) == 0xe240c700 /*sub ip,??,#__*/) {
+               pv -= (uintptr_t) ((mcode & 0x000000ff) << 18);
+               mcode = pc[++mcode_idx];
+       }
+
+       /* if this was shifted by 10 bits, we have to load additional instructions */
+       if ((mcode & 0xfff0ff00) == 0xe240cb00 /*sub ip,??,#__*/) {
+               pv -= (uintptr_t) ((mcode & 0x000000ff) << 10);
+               mcode = pc[++mcode_idx];
+       }
+
+       /* this is the default path with just one instruction, shifted by 2 or no bits */
+       if ((mcode & 0xfff0ff00) == 0xe240cf00 /*sub ip,??,#__*/)
+               pv -= (uintptr_t) ((mcode & 0x000000ff) << 2);
+       else if ((mcode & 0xffffff00) == 0xe24fc000 /*sub ip,pc,#__*/)
+               pv -= (uintptr_t) (mcode & 0x000000ff);
        else {
                /* if this happens, we got an unexpected instruction at (*ra) */
-               vm_abort("Unable to find method: %p (instr=%x)", ra, mcode1);
+               vm_abort("Unable to find method: %p (instr=%x)", ra, mcode);
        }
 
-       /* if we have a RECOMPUTE_IP there can be more than one instruction */
-       mcode2 = pc[1];
-       mcode3 = pc[2];
-       if ((mcode2 & 0xffffff00) == 0xe24ccb00 /*sub ip,ip,#__*/)
-               pv -= (uintptr_t) ((mcode2 & 0x000000ff) << 10);
-       if ((mcode3 & 0xffffff00) == 0xe24cc700 /*sub ip,ip,#__*/)
-               pv -= (uintptr_t) ((mcode3 & 0x000000ff) << 18);
-
        /* we used PC-relative adressing; but now it is LR-relative */
        pv += 8;
 
index b16f618daee01e8d11ded223d6c006af98589421..f3d70b2544957066c6817dccf62657f5045cf88b 100644 (file)
@@ -2,6 +2,7 @@
 
    Copyright (C) 1996-2005, 2006, 2007, 2008
    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+   Copyright (C) 2008 Theobroma Systems Ltd.
 
    This file is part of CACAO.
 
 
 #include "mm/memory.h"
 
-#include "native/native.h"
+#include "native/native.hpp"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/class.h"
-#include "vm/field.h"
+#include "vm/field.hpp"
 #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/patcher-common.hpp"
 
 
-#define PATCH_BACK_ORIGINAL_MCODE \
-    *((u4 *) pr->mpc) = (u4) pr->mcode; \
-    md_icacheflush((u1 *) pr->mpc, 1 * 4);
-
 #define gen_resolveload(inst,offset) \
        assert((offset) >= -0x0fff && (offset) <= 0x0fff); \
        assert(!((inst) & 0x0fff)); \
@@ -94,7 +91,28 @@ void patch_md(s4 md_patch, ptrint dest, void* ref)
 
 void patcher_patch_code(patchref_t *pr)
 {
-       PATCH_BACK_ORIGINAL_MCODE;
+    *((uint32_t*) pr->mpc) = (uint32_t) pr->mcode;
+    md_icacheflush((void*) pr->mpc, 1 * 4);
+}
+
+
+/**
+ * Check if the trap instruction at the given PC is valid.
+ *
+ * @param pc Program counter.
+ *
+ * @return true if valid, false otherwise.
+ */
+bool patcher_is_valid_trap_instruction_at(void* pc)
+{
+       uint32_t mcode = *((uint32_t*) pc);
+
+       // Check for the undefined instruction we use.
+       if ((mcode & 0x0ff000f0) != 0x07f000f0) {
+               return false;
+       }
+
+       return true;
 }
 
 
@@ -109,31 +127,25 @@ void patcher_patch_code(patchref_t *pr)
 
 bool patcher_get_putstatic(patchref_t *pr)
 {
-       unresolved_field *uf;
-       u1               *datap;
-       fieldinfo        *fi;
-
-       /* get stuff from the stack */
+       unresolved_field* uf    = (unresolved_field *) pr->ref;
+       uintptr_t*        datap = (uintptr_t*)         pr->datap;
 
-       uf    = (unresolved_field *) pr->ref;
-       datap = (u1 *)               pr->datap;
+       // Resolve the field.
+       fieldinfo* fi = resolve_field_eager(uf);
 
-       /* get the fieldinfo */
-
-       if (!(fi = resolve_field_eager(uf)))
+       if (fi == NULL)
                return false;
 
-       /* check if the field's class is initialized */
-
+       // Check if the field's class is initialized.
        if (!(fi->clazz->state & CLASS_INITIALIZED))
                if (!initialize_class(fi->clazz))
                        return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
-
-       /* patch the field value's address */
+       // Patch the field value's address.
+       *datap = (uintptr_t) fi->value;
 
-       *((intptr_t *) datap) = (intptr_t) fi->value;
+       // Patch back the original code.
+       patcher_patch_code(pr);
 
        return true;
 }
@@ -150,29 +162,16 @@ bool patcher_get_putstatic(patchref_t *pr)
 
 bool patcher_get_putfield(patchref_t *pr)
 {
-       u1                *ra;
-       u4                 mcode;
-       unresolved_field  *uf;
-       fieldinfo         *fi;
+       uint32_t*         pc = (uint32_t*)         pr->mpc;
+       unresolved_field* uf = (unresolved_field*) pr->ref;
 
-       /* get stuff from the stack */
-       ra    = (u1*)                 pr->mpc;
-       mcode =                       pr->mcode;
-       uf    = (unresolved_field*)   pr->ref;
+       // Resolve the field.
+       fieldinfo* fi = resolve_field_eager(uf);
 
-       /* get the fieldinfo */
-
-       if (!(fi = resolve_field_eager(uf)))
+       if (fi == NULL)
                return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
-
-       /* if we show disassembly, we have to skip the nop */
-
-       if (opt_shownops)
-               ra = ra + 1 * 4;
-
-       /* patch the field's offset into the instruction */
+       // Patch the field's offset into the instruction.
 
        switch(fi->type) {
        case TYPE_ADR:
@@ -181,7 +180,7 @@ bool patcher_get_putfield(patchref_t *pr)
        case TYPE_FLT:
 #endif
                assert(fi->offset <= 0x0fff);
-               *((u4 *) (ra + 0 * 4)) |= (fi->offset & 0x0fff);
+               pr->mcode |= (fi->offset & 0x0fff);
                break;
 
        case TYPE_LNG:
@@ -189,23 +188,25 @@ bool patcher_get_putfield(patchref_t *pr)
        case TYPE_DBL:
 #endif
                assert((fi->offset + 4) <= 0x0fff);
-               *((u4 *) (ra + 0 * 4)) |= ((fi->offset + 0) & 0x0fff);
-               *((u4 *) (ra + 1 * 4)) &= 0xfffff000;
-               *((u4 *) (ra + 1 * 4)) |= ((fi->offset + 4) & 0x0fff);
+               pr->mcode |= ((fi->offset + 0) & 0x0fff);
+               pc[1] &= 0xfffff000;
+               pc[1] |= ((fi->offset + 4) & 0x0fff);
                break;
 
 #if !defined(ENABLE_SOFTFLOAT)
        case TYPE_FLT:
        case TYPE_DBL:
                assert(fi->offset <= 0x03ff);
-               *((u4 *) (ra + 0 * 4)) |= ((fi->offset >> 2) & 0x00ff);
+               pr->mcode |= ((fi->offset >> 2) & 0x00ff);
                break;
 #endif
        }
 
-       /* synchronize instruction cache */
+       // Synchronize instruction cache.
+       md_icacheflush(pc, 2 * 4);
 
-       md_icacheflush(ra, 2 * 4);
+       // Patch back the original code.
+       patcher_patch_code(pr);
 
        return true;
 }
@@ -238,25 +239,20 @@ bool patcher_get_putfield(patchref_t *pr)
 
 bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
 {
-       constant_classref *cr;
-       u1                *datap;
-       classinfo         *c;
-
-       /* get stuff from the stack */
-
-       cr    = (constant_classref *) pr->ref;
-       datap = (u1 *)                pr->datap;
+       constant_classref* cr    = (constant_classref *) pr->ref;
+       uintptr_t*         datap = (uintptr_t*)          pr->datap;
 
-       /* get the classinfo */
+       // Resolve the class.
+       classinfo* c = resolve_classref_eager(cr);
 
-       if (!(c = resolve_classref_eager(cr)))
+       if (c == NULL)
                return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
+       // Patch the classinfo pointer.
+       *datap = (uintptr_t) c;
 
-       /* patch the classinfo pointer */
-
-       *((ptrint *) datap) = (ptrint) c;
+       // Patch back the original code.
+       patcher_patch_code(pr);
 
        return true;
 }
@@ -275,25 +271,20 @@ bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
 
 bool patcher_invokestatic_special(patchref_t *pr)
 {
-       unresolved_method *um;
-       u1                *datap;
-       methodinfo        *m;
-
-       /* get stuff from the stack */
+       unresolved_method* um    = (unresolved_method*) pr->ref;
+       uintptr_t*         datap = (uintptr_t*)         pr->datap;
 
-       um    = (unresolved_method*) pr->ref;
-       datap = (u1 *)               pr->datap;
+       // Reolve the method.
+       methodinfo* m = resolve_method_eager(um);
 
-       /* get the methodinfo */
-
-       if (!(m = resolve_method_eager(um)))
+       if (m == NULL)
                return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
-
-       /* patch stubroutine */
+       // Patch stubroutine.
+       *datap = (uintptr_t) m->stubroutine;
 
-       *((ptrint *) datap) = (ptrint) m->stubroutine;
+       // Patch back the original code.
+       patcher_patch_code(pr);
 
        return true;
 }
@@ -313,34 +304,23 @@ bool patcher_invokestatic_special(patchref_t *pr)
 
 bool patcher_invokevirtual(patchref_t *pr)
 {
-       u1                *ra;
-       unresolved_method *um;
-       methodinfo        *m;
-
-       /* get stuff from the stack */
+       uint32_t*          pc = (uint32_t*)           pr->mpc;
+       unresolved_method* um = (unresolved_method *) pr->ref;
 
-       ra = (u1 *)                pr->mpc;
-       um = (unresolved_method *) pr->ref;
+       // Resolve the method.
+       methodinfo* m = resolve_method_eager(um);
 
-       /* get the methodinfo */
-
-       if (!(m = resolve_method_eager(um)))
+       if (m == NULL)
                return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
-
-       /* if we show disassembly, we have to skip the nop */
-
-       if (opt_shownops)
-               ra = ra + 1 * 4;
+       // Patch vftbl index.
+       gen_resolveload(pc[1], (int32_t) (OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex));
 
-       /* patch vftbl index */
+       // Synchronize instruction cache.
+       md_icacheflush(pc + 1, 1 * 4);
 
-       gen_resolveload(*((s4 *) (ra + 1 * 4)), (s4) (OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex));
-
-       /* synchronize instruction cache */
-
-       md_icacheflush(ra + 1 * 4, 1 * 4);
+       // Patch back the original code.
+       patcher_patch_code(pr);
 
        return true;
 }
@@ -362,38 +342,26 @@ bool patcher_invokevirtual(patchref_t *pr)
 
 bool patcher_invokeinterface(patchref_t *pr)
 {
-       u1                *ra;
-       unresolved_method *um;
-       methodinfo        *m;
-
-       /* get stuff from the stack */
+       uint32_t*          pc = (uint32_t*)           pr->mpc;
+       unresolved_method* um = (unresolved_method *) pr->ref;
 
-       ra = (u1 *)                pr->mpc;
-       um = (unresolved_method *) pr->ref;
+       // Resolve the method.
+       methodinfo* m = resolve_method_eager(um);
 
-       /* get the methodinfo */
-
-       if (!(m = resolve_method_eager(um)))
+       if (m == NULL)
                return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
-
-       /* if we show disassembly, we have to skip the nop */
-
-       if (opt_shownops)
-               ra = ra + 1 * 4;
+       // Patch interfacetable index.
+       gen_resolveload(pc[1], (int32_t) (OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr*) * m->clazz->index));
 
-       /* patch interfacetable index */
+       // Patch method offset.
+       gen_resolveload(pc[2], (int32_t) (sizeof(methodptr) * (m - m->clazz->methods)));
 
-       gen_resolveload(*((s4 *) (ra + 1 * 4)), (s4) (OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr*) * m->clazz->index));
+       // Synchronize instruction cache.
+       md_icacheflush(pc + 1, 2 * 4);
 
-       /* patch method offset */
-
-       gen_resolveload(*((s4 *) (ra + 2 * 4)), (s4) (sizeof(methodptr) * (m - m->clazz->methods)));
-
-       /* synchronize instruction cache */
-
-       md_icacheflush(ra + 1 * 4, 2 * 4);
+       // Patch back the original code.
+       patcher_patch_code(pr);
 
        return true;
 }
@@ -409,25 +377,20 @@ bool patcher_invokeinterface(patchref_t *pr)
 
 bool patcher_resolve_classref_to_flags(patchref_t *pr)
 {
-       constant_classref *cr;
-       u1                *datap;
-       classinfo         *c;
+       constant_classref* cr    = (constant_classref*) pr->ref;
+       int32_t*           datap = (int32_t*)           pr->datap;
 
-       /* get stuff from the stack */
+       // Resolve the class.
+       classinfo* c = resolve_classref_eager(cr);
 
-       cr    = (constant_classref *) pr->ref;
-       datap = (u1 *)                pr->datap;
-
-       /* get the classinfo */
-
-       if (!(c = resolve_classref_eager(cr)))
+       if (c == NULL)
                return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
-
-       /* patch class flags */
+       // Patch class flags.
+       *datap = (int32_t) c->flags;
 
-       *((s4 *) datap) = (s4) c->flags;
+       // Patch back the original code.
+       patcher_patch_code(pr);
 
        return true;
 }
@@ -443,25 +406,20 @@ bool patcher_resolve_classref_to_flags(patchref_t *pr)
 
 bool patcher_resolve_classref_to_index(patchref_t *pr)
 {
-       constant_classref *cr;
-       u1                *datap;
-       classinfo         *c;
+       constant_classref* cr    = (constant_classref*) pr->ref;
+       int32_t*           datap = (int32_t*)           pr->datap;
 
-       /* get stuff from the stack */
+       // Resolve the class.
+       classinfo* c = resolve_classref_eager(cr);
 
-       cr    = (constant_classref *) pr->ref;
-       datap = (u1 *)                pr->datap;
-
-       /* get the classinfo */
-
-       if (!(c = resolve_classref_eager(cr)))
+       if (c == NULL)
                return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
-
-       /* patch super class index */
+       // Patch super class index.
+       *datap = (int32_t) c->index;
 
-       *((s4 *) datap) = (s4) c->index;
+       // Patch back the original code.
+       patcher_patch_code(pr);
 
        return true;
 }
@@ -477,25 +435,21 @@ bool patcher_resolve_classref_to_index(patchref_t *pr)
 
 bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
 {
-       constant_classref *cr;
-       u1                *datap;
-       classinfo         *c;
+       constant_classref* cr    = (constant_classref*) pr->ref;
+       uintptr_t*         datap = (uintptr_t*)         pr->datap;
 
-       /* get stuff from the stack */
+       // Resolve the class.
 
-       cr    = (constant_classref *) pr->ref;
-       datap = (u1 *)                pr->datap;
+       classinfo* c = resolve_classref_eager(cr);
 
-       /* get the classinfo */
-
-       if (!(c = resolve_classref_eager(cr)))
+       if (c == NULL)
                return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
-
-       /* patch super class' vftbl */
+       // Patch super class' vftbl.
+       *datap = (uintptr_t) c->vftbl;
 
-       *((ptrint *) datap) = (ptrint) c->vftbl;
+       // Patch back the original code.
+       patcher_patch_code(pr);
 
        return true;
 }
index ecb44b785fd2b965f31466e0e213fffaca2af1b3..9ea6f4da5c97ce6efaca10364e1e50a84fb40d84 100644 (file)
 
 #include <stdint.h>
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #include "vm/types.h"
 
 #include "vm/global.h"
@@ -42,6 +38,10 @@ extern "C" {
 
 /* function prototypes ********************************************************/
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /* machine dependent initialization */
 s4   asm_md_init(void);
 
@@ -111,7 +111,7 @@ void asm_escape_check(java_object_t *obj);
 #endif
 
 #ifdef __cplusplus
-}
+} // extern "C"
 #endif
 
 #endif /* _ASMPART_H */
diff --git a/src/vm/jit/builtin.cpp b/src/vm/jit/builtin.cpp
new file mode 100644 (file)
index 0000000..f4d23e8
--- /dev/null
@@ -0,0 +1,2415 @@
+/* src/vm/jit/builtin.cpp - functions for unsupported operations
+
+   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.
+
+   Contains C functions for JavaVM Instructions that cannot be
+   translated to machine language directly. Consequently, the
+   generated machine code for these instructions contains function
+   calls instead of machine instructions, using the C calling
+   convention.
+
+*/
+
+
+#include "config.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+
+#include "vm/types.h"
+
+#include "arch.h"
+#include "md-abi.h"
+
+#include "fdlibm/fdlibm.h"
+#if defined(__CYGWIN__) && defined(Bias)
+# undef Bias
+#endif
+
+#include "mm/gc.hpp"
+#include "mm/memory.h"
+
+#include "native/llni.h"
+
+#include "threads/lock.hpp"
+#include "threads/mutex.hpp"
+#include "threads/thread.hpp"
+
+#include "toolbox/logging.h"
+#include "toolbox/util.h"
+
+#include "vm/array.hpp"
+#include "vm/jit/builtin.hpp"
+#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.hpp"
+#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/stubs.hpp"
+#include "vm/jit/trace.hpp"
+
+#if defined(ENABLE_VMLOG)
+#include <vmlog_cacao.h>
+#endif
+
+
+/* include builtin tables *****************************************************/
+
+#include "vm/jit/builtintable.inc"
+
+
+CYCLES_STATS_DECLARE(builtin_new         ,100,5)
+CYCLES_STATS_DECLARE(builtin_overhead    , 80,1)
+
+
+/*============================================================================*/
+/* BUILTIN TABLE MANAGEMENT FUNCTIONS                                         */
+/*============================================================================*/
+
+/* builtintable_init ***********************************************************
+
+   Parse the descriptors of builtin functions and create the parsed
+   descriptors.
+
+*******************************************************************************/
+
+static bool builtintable_init(void)
+{
+       descriptor_pool    *descpool;
+       builtintable_entry *bte;
+       methodinfo         *m;
+
+       // Create new dump memory area.
+       DumpMemoryArea dma;
+
+       /* create a new descriptor pool */
+
+       descpool = descriptor_pool_new(class_java_lang_Object);
+
+       /* add some entries we need */
+
+       if (!descriptor_pool_add_class(descpool, utf_java_lang_Object))
+               return false;
+
+       if (!descriptor_pool_add_class(descpool, utf_java_lang_Class))
+               return false;
+
+       /* first add all descriptors to the pool */
+
+       for (bte = builtintable_internal; bte->fp != NULL; bte++) {
+               bte->name       = utf_new_char(bte->cname);
+               bte->descriptor = utf_new_char(bte->cdescriptor);
+
+               if (!descriptor_pool_add(descpool, bte->descriptor, NULL))
+                       return false;
+       }
+
+       for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
+               bte->descriptor = utf_new_char(bte->cdescriptor);
+
+               if (!descriptor_pool_add(descpool, bte->descriptor, NULL))
+                       return false;
+       }
+
+       for (bte = builtintable_function; bte->fp != NULL; bte++) {
+               bte->classname  = utf_new_char(bte->cclassname);
+               bte->name       = utf_new_char(bte->cname);
+               bte->descriptor = utf_new_char(bte->cdescriptor);
+
+               if (!descriptor_pool_add(descpool, bte->descriptor, NULL))
+                       return false;
+       }
+
+       /* create the class reference table */
+
+       (void) descriptor_pool_create_classrefs(descpool, NULL);
+
+       /* allocate space for the parsed descriptors */
+
+       descriptor_pool_alloc_parsed_descriptors(descpool);
+
+       /* Now parse all descriptors.  NOTE: builtin-functions are treated
+          like static methods (no `this' pointer). */
+
+       for (bte = builtintable_internal; bte->fp != NULL; bte++) {
+               bte->md =
+                       descriptor_pool_parse_method_descriptor(descpool,
+                                                                                                       bte->descriptor,
+                                                                                                       ACC_STATIC | ACC_METHOD_BUILTIN,
+                                                                                                       NULL);
+
+               /* generate a builtin stub if we need one */
+
+               if (bte->flags & BUILTINTABLE_FLAG_STUB) {
+                       m = method_new_builtin(bte);
+                       BuiltinStub::generate(m, bte);
+               }
+       }
+
+       for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
+               bte->md =
+                       descriptor_pool_parse_method_descriptor(descpool,
+                                                                                                       bte->descriptor,
+                                                                                                       ACC_STATIC | ACC_METHOD_BUILTIN,
+                                                                                                       NULL);
+
+               /* no stubs should be needed for this table */
+
+               assert(!bte->flags & BUILTINTABLE_FLAG_STUB);
+       }
+
+       for (bte = builtintable_function; bte->fp != NULL; bte++) {
+               bte->md =
+                       descriptor_pool_parse_method_descriptor(descpool,
+                                                                                                       bte->descriptor,
+                                                                                                       ACC_STATIC | ACC_METHOD_BUILTIN,
+                                                                                                       NULL);
+
+               /* generate a builtin stub if we need one */
+
+               if (bte->flags & BUILTINTABLE_FLAG_STUB) {
+                       m = method_new_builtin(bte);
+                       BuiltinStub::generate(m, bte);
+               }
+       }
+
+       return true;
+}
+
+
+/* builtintable_comparator *****************************************************
+
+   qsort comparator for the automatic builtin table.
+
+*******************************************************************************/
+
+static int builtintable_comparator(const void *a, const void *b)
+{
+       builtintable_entry *bte1;
+       builtintable_entry *bte2;
+
+       bte1 = (builtintable_entry *) a;
+       bte2 = (builtintable_entry *) b;
+
+       return (bte1->opcode < bte2->opcode) ? -1 : (bte1->opcode > bte2->opcode);
+}
+
+
+/* builtintable_sort_automatic *************************************************
+
+   Sorts the automatic builtin table.
+
+*******************************************************************************/
+
+static void builtintable_sort_automatic(void)
+{
+       s4 entries;
+
+       /* calculate table size statically (`- 1' comment see builtintable.inc) */
+
+       entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
+
+       qsort(builtintable_automatic, entries, sizeof(builtintable_entry),
+                 builtintable_comparator);
+}
+
+
+/* builtin_init ****************************************************************
+
+   Initialize the global table of builtin functions.
+
+*******************************************************************************/
+
+bool builtin_init(void)
+{
+       TRACESUBSYSTEMINITIALIZATION("builtin_init");
+
+       /* initialize the builtin tables */
+
+       if (!builtintable_init())
+               return false;
+
+       /* sort builtin tables */
+
+       builtintable_sort_automatic();
+
+       return true;
+}
+
+
+/* builtintable_get_by_key *****************************************************
+
+   Returns a key for the given builtintable_entry object which is suitable
+   for retrieving the instance again by calling builtintable_get_by_key.
+
+   The key can be regarded fixed between multiple runs of the JVM.
+
+*******************************************************************************/
+
+s4 builtintable_get_key(builtintable_entry *bte)
+{
+       s4 entries;
+/*
+       int i;
+       entries = sizeof(builtintable_internal) / sizeof(builtintable_entry) - 1;
+       for (i = 0; i < entries; i++)
+               if (&builtintable_internal[i] == bte)
+                       return i + 1;
+
+       entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
+       for (i = 0; i < entries; i++)
+               if (&builtintable_automatic[i] == bte)
+                       return -i;
+
+       entries = sizeof(builtintable_function) / sizeof(builtintable_entry) - 1;
+       for (i = 0; i < entries; i++)
+               if (&builtintable_function[i] == bte)
+                       return -1000 - i;
+*/
+
+       entries = sizeof(builtintable_internal) / sizeof(builtintable_entry) - 1;
+       if (&builtintable_internal[0] <= bte
+               && &builtintable_internal[entries - 1] >= bte)
+       {
+               return (s4) (bte - &builtintable_internal[0]) + 1;
+       }
+
+       entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
+       if (&builtintable_automatic[0] <= bte
+               && &builtintable_automatic[entries - 1] >= bte)
+       {
+               return -(s4) (bte - &builtintable_automatic[0]);
+       }
+
+       entries = sizeof(builtintable_function) / sizeof(builtintable_entry) - 1;
+       if (&builtintable_function[0] <= bte
+               && &builtintable_function[entries - 1] >= bte)
+       {
+               return -1000 - (s4) (bte - &builtintable_function[0]);
+       }
+
+       /* builtintable_entry is not in our tables. */
+       assert (0);
+
+       return 0;
+}
+
+/* builtintable_get_by_key *****************************************************
+
+   Retrieves an entry in the internal and automatic builtin functions tables
+   using a key that was retrived previously with builtintable_get_key()
+
+*******************************************************************************/
+
+builtintable_entry *builtintable_get_by_key(s4 key)
+{
+       /* If key is positive it is the index into builtintable_internal. If it is
+        * negative it is the index into builtintable_automatic. If it is <= -1000
+     * it is the index into builtintable_function.
+     */
+       return (key > 0)
+               ? &builtintable_internal[key - 1]
+               : (key > -1000 ? &builtintable_automatic[-key] : &builtintable_function[-(1000 + key)]);
+}
+
+/* builtintable_get_internal ***************************************************
+
+   Finds an entry in the builtintable for internal functions and
+   returns the a pointer to the structure.
+
+*******************************************************************************/
+
+builtintable_entry *builtintable_get_internal(functionptr fp)
+{
+       builtintable_entry *bte;
+
+       for (bte = builtintable_internal; bte->fp != NULL; bte++) {
+               if (bte->fp == fp)
+                       return bte;
+       }
+
+       return NULL;
+}
+
+
+/* builtintable_get_automatic **************************************************
+
+   Finds an entry in the builtintable for functions which are replaced
+   automatically and returns the a pointer to the structure.
+
+*******************************************************************************/
+
+builtintable_entry *builtintable_get_automatic(s4 opcode)
+{
+       builtintable_entry *first;
+       builtintable_entry *last;
+       builtintable_entry *middle;
+       s4                  half;
+       s4                  entries;
+
+       /* calculate table size statically (`- 1' comment see builtintable.inc) */
+
+       entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
+
+       first = builtintable_automatic;
+       last = builtintable_automatic + entries;
+
+       while (entries > 0) {
+               half = entries / 2;
+               middle = first + half;
+
+               if (middle->opcode < opcode) {
+                       first = middle + 1;
+                       entries -= half + 1;
+               }
+               else
+                       entries = half;
+       }
+
+       return (first != last ? first : NULL);
+}
+
+
+/* builtintable_replace_function ***********************************************
+
+   XXX
+
+*******************************************************************************/
+
+#if defined(ENABLE_JIT)
+bool builtintable_replace_function(void *iptr_)
+{
+       constant_FMIref    *mr;
+       builtintable_entry *bte;
+       instruction        *iptr;
+
+       iptr = (instruction *) iptr_; /* twisti will kill me ;) */
+
+       /* get name and descriptor of the function */
+
+       switch (iptr->opc) {
+       case ICMD_INVOKESTATIC:
+               /* The instruction MUST be resolved, otherwise we run into
+                  lazy loading troubles.  Anyway, we should/can only replace
+                  very VM-close functions. */
+
+               if (INSTRUCTION_IS_UNRESOLVED(iptr))
+                       return false;
+
+               mr = iptr->sx.s23.s3.fmiref;
+               break;  
+
+       default:
+               return false;
+       }
+
+       /* search the function table */
+
+       for (bte = builtintable_function; bte->fp != NULL; bte++) {
+               if ((METHODREF_CLASSNAME(mr) == bte->classname) &&
+                       (mr->name                == bte->name) &&
+                       (mr->descriptor          == bte->descriptor)) {
+
+                       /* set the values in the instruction */
+
+                       iptr->opc           = bte->opcode;
+                       iptr->sx.s23.s3.bte = bte;
+
+                       if (bte->flags & BUILTINTABLE_FLAG_EXCEPTION)
+                               iptr->flags.bits |= INS_FLAG_CHECK;
+                       else
+                               iptr->flags.bits &= ~INS_FLAG_CHECK;
+
+                       return true;
+               }
+       }
+
+       return false;
+}
+#endif /* defined(ENABLE_JIT) */
+
+
+/*============================================================================*/
+/* INTERNAL BUILTIN FUNCTIONS                                                 */
+/*============================================================================*/
+
+/* builtin_instanceof **********************************************************
+
+   Checks if an object is an instance of some given class (or subclass
+   of that class). If class is an interface, checks if the interface
+   is implemented.
+
+   RETURN VALUE:
+     1......o is an instance of class or implements the interface
+     0......otherwise or if o == NULL
+
+   NOTE: This builtin can be called from NATIVE code only.
+
+*******************************************************************************/
+
+bool builtin_instanceof(java_handle_t *o, classinfo *c)
+{
+       classinfo *oc;
+
+       if (o == NULL)
+               return 0;
+
+       LLNI_class_get(o, oc);
+
+       return class_isanysubclass(oc, c);
+}
+
+
+
+/* builtin_checkcast ***********************************************************
+
+   The same as builtin_instanceof but with the exception
+   that 1 is returned when (o == NULL).
+
+   NOTE: This builtin can be called from NATIVE code only.
+
+*******************************************************************************/
+
+bool builtin_checkcast(java_handle_t *o, classinfo *c)
+{
+       classinfo *oc;
+
+       if (o == NULL)
+               return 1;
+
+       LLNI_class_get(o, oc);
+
+       if (class_isanysubclass(oc, c))
+               return 1;
+
+       return 0;
+}
+
+
+/* builtin_descriptorscompatible ***********************************************
+
+   Checks if two array type descriptors are assignment compatible.
+
+   RETURN VALUE:
+      1......target = desc is possible
+      0......otherwise
+                       
+*******************************************************************************/
+
+static bool builtin_descriptorscompatible(arraydescriptor *desc, arraydescriptor *target)
+{
+       if (desc == target)
+               return 1;
+
+       if (desc->arraytype != target->arraytype)
+               return 0;
+
+       if (desc->arraytype != ARRAYTYPE_OBJECT)
+               return 1;
+       
+       /* {both arrays are arrays of references} */
+
+       if (desc->dimension == target->dimension) {
+               if (!desc->elementvftbl)
+                       return 0;
+               /* an array which contains elements of interface types is
+           allowed to be casted to Object (JOWENN)*/
+
+               if ((desc->elementvftbl->baseval < 0) &&
+                       (target->elementvftbl->baseval == 1))
+                       return 1;
+
+               return class_isanysubclass(desc->elementvftbl->clazz,
+                                                                  target->elementvftbl->clazz);
+       }
+
+       if (desc->dimension < target->dimension)
+               return 0;
+
+       /* {desc has higher dimension than target} */
+
+       return class_isanysubclass(pseudo_class_Arraystub,
+                                                          target->elementvftbl->clazz);
+}
+
+
+/* builtin_arraycheckcast ******************************************************
+
+   Checks if an object is really a subtype of the requested array
+   type.  The object has to be an array to begin with. For simple
+   arrays (int, short, double, etc.) the types have to match exactly.
+   For arrays of objects, the type of elements in the array has to be
+   a subtype (or the same type) of the requested element type. For
+   arrays of arrays (which in turn can again be arrays of arrays), the
+   types at the lowest level have to satisfy the corresponding sub
+   class relation.
+
+   NOTE: This is a FAST builtin and can be called from JIT code only.
+
+*******************************************************************************/
+
+bool builtin_fast_arraycheckcast(java_object_t *o, classinfo *targetclass)
+{
+       arraydescriptor *desc;
+
+       if (o == NULL)
+               return 1;
+
+       desc = o->vftbl->arraydesc;
+
+       if (desc == NULL)
+               return 0;
+       return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc);
+}
+
+
+/* builtin_fast_arrayinstanceof ************************************************
+
+   NOTE: This is a FAST builtin and can be called from JIT code only.
+
+*******************************************************************************/
+
+bool builtin_fast_arrayinstanceof(java_object_t *o, classinfo *targetclass)
+{
+       if (o == NULL)
+               return 0;
+
+       return builtin_fast_arraycheckcast(o, targetclass);
+}
+
+
+/* builtin_arrayinstanceof *****************************************************
+
+   NOTE: This builtin can be called from NATIVE code only.
+
+*******************************************************************************/
+
+bool builtin_arrayinstanceof(java_handle_t *h, classinfo *targetclass)
+{
+       bool result;
+
+       LLNI_CRITICAL_START;
+
+       result = builtin_fast_arrayinstanceof(LLNI_UNWRAP(h), targetclass);
+
+       LLNI_CRITICAL_END;
+
+       return result;
+}
+
+
+/* builtin_throw_exception *****************************************************
+
+   Sets the exception pointer with the thrown exception and prints some
+   debugging information.
+   
+   NOTE: This is a FAST builtin and can be called from JIT code,
+   or from asm_vm_call_method.
+
+*******************************************************************************/
+
+void *builtin_throw_exception(java_object_t *xptr)
+{
+#if !defined(NDEBUG)
+       /* print exception trace */
+
+       if (opt_TraceExceptions)
+               trace_exception_builtin(xptr);
+#endif /* !defined(NDEBUG) */
+
+       /* actually set the exception */
+
+       exceptions_set_exception(LLNI_QUICKWRAP(xptr));
+
+       /* Return a NULL pointer.  This is required for vm_call_method to
+          check for an exception.  This is for convenience. */
+
+       return NULL;
+}
+
+
+/* builtin_retrieve_exception **************************************************
+
+   Gets and clears the exception pointer of the current thread.
+
+   RETURN VALUE:
+      the exception object, or NULL if no exception was thrown.
+
+   NOTE: This is a FAST builtin and can be called from JIT code,
+   or from the signal handlers.
+
+*******************************************************************************/
+
+java_object_t *builtin_retrieve_exception(void)
+{
+       java_handle_t *h;
+       java_object_t *o;
+
+       /* actually get and clear the exception */
+
+       h = exceptions_get_and_clear_exception();
+       o = LLNI_UNWRAP(h);
+
+       return o;
+}
+
+
+/* builtin_canstore ************************************************************
+
+   Checks, if an object can be stored in an array.
+
+   RETURN VALUE:
+      1......possible
+      0......otherwise (throws an ArrayStoreException)
+
+   NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
+
+*******************************************************************************/
+
+bool builtin_canstore(java_handle_objectarray_t *oa, java_handle_t *o)
+{
+       bool result;
+
+       LLNI_CRITICAL_START;
+
+       result = builtin_fast_canstore(LLNI_DIRECT(oa), LLNI_UNWRAP(o));
+
+       LLNI_CRITICAL_END;
+
+       /* if not possible, throw an exception */
+
+       if (result == 0)
+               exceptions_throw_arraystoreexception();
+
+       return result;
+}
+
+
+/* builtin_fast_canstore *******************************************************
+
+   Checks, if an object can be stored in an array.
+
+   RETURN VALUE:
+      1......possible
+      0......otherwise (no exception thrown!)
+
+   NOTE: This is a FAST builtin and can be called from JIT code only.
+
+*******************************************************************************/
+
+bool builtin_fast_canstore(java_objectarray_t *oa, java_object_t *o)
+{
+       arraydescriptor *desc;
+       arraydescriptor *valuedesc;
+       vftbl_t         *componentvftbl;
+       vftbl_t         *valuevftbl;
+       int32_t          baseval;
+       uint32_t         diffval;
+       bool             result;
+
+       if (o == NULL)
+               return 1;
+
+       /* The following is guaranteed (by verifier checks):
+        *
+        *     *) oa->...vftbl->arraydesc != NULL
+        *     *) oa->...vftbl->arraydesc->componentvftbl != NULL
+        *     *) o->vftbl is not an interface vftbl
+        */
+
+       desc           = oa->header.objheader.vftbl->arraydesc;
+       componentvftbl = desc->componentvftbl;
+       valuevftbl     = o->vftbl;
+       valuedesc      = valuevftbl->arraydesc;
+
+       if ((desc->dimension - 1) == 0) {
+               /* {oa is a one-dimensional array} */
+               /* {oa is an array of references} */
+               
+               if (valuevftbl == componentvftbl)
+                       return 1;
+
+               linker_classrenumber_mutex->lock();
+
+               baseval = componentvftbl->baseval;
+
+               if (baseval <= 0) {
+                       /* an array of interface references */
+
+                       result = ((valuevftbl->interfacetablelength > -baseval) &&
+                                         (valuevftbl->interfacetable[baseval] != NULL));
+               }
+               else {
+                       diffval = valuevftbl->baseval - componentvftbl->baseval;
+                       result  = diffval <= (uint32_t) componentvftbl->diffval;
+               }
+
+               linker_classrenumber_mutex->unlock();
+       }
+       else if (valuedesc == NULL) {
+               /* {oa has dimension > 1} */
+               /* {componentvftbl->arraydesc != NULL} */
+
+               /* check if o is an array */
+
+               return 0;
+       }
+       else {
+               /* {o is an array} */
+
+               result = builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
+       }
+
+       /* return result */
+
+       return result;
+}
+
+
+/* This is an optimized version where a is guaranteed to be one-dimensional */
+bool builtin_fast_canstore_onedim(java_objectarray_t *a, java_object_t *o)
+{
+       arraydescriptor *desc;
+       vftbl_t         *elementvftbl;
+       vftbl_t         *valuevftbl;
+       int32_t          baseval;
+       uint32_t         diffval;
+       bool             result;
+       
+       if (o == NULL)
+               return 1;
+
+       /* The following is guaranteed (by verifier checks):
+        *
+        *     *) a->...vftbl->arraydesc != NULL
+        *     *) a->...vftbl->arraydesc->elementvftbl != NULL
+        *     *) a->...vftbl->arraydesc->dimension == 1
+        *     *) o->vftbl is not an interface vftbl
+        */
+
+       desc = a->header.objheader.vftbl->arraydesc;
+    elementvftbl = desc->elementvftbl;
+       valuevftbl = o->vftbl;
+
+       /* {a is a one-dimensional array} */
+       
+       if (valuevftbl == elementvftbl)
+               return 1;
+
+       linker_classrenumber_mutex->lock();
+
+       baseval = elementvftbl->baseval;
+
+       if (baseval <= 0) {
+               /* an array of interface references */
+               result = ((valuevftbl->interfacetablelength > -baseval) &&
+                                 (valuevftbl->interfacetable[baseval] != NULL));
+       }
+       else {
+               diffval = valuevftbl->baseval - elementvftbl->baseval;
+               result  = diffval <= (uint32_t) elementvftbl->diffval;
+       }
+
+       linker_classrenumber_mutex->unlock();
+
+       return result;
+}
+
+
+/* This is an optimized version where a is guaranteed to be a
+ * one-dimensional array of a class type */
+bool builtin_fast_canstore_onedim_class(java_objectarray_t *a, java_object_t *o)
+{
+       vftbl_t  *elementvftbl;
+       vftbl_t  *valuevftbl;
+       uint32_t  diffval;
+       bool      result;
+       
+       if (o == NULL)
+               return 1;
+
+       /* The following is guaranteed (by verifier checks):
+        *
+        *     *) a->...vftbl->arraydesc != NULL
+        *     *) a->...vftbl->arraydesc->elementvftbl != NULL
+        *     *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
+        *     *) a->...vftbl->arraydesc->dimension == 1
+        *     *) o->vftbl is not an interface vftbl
+        */
+
+    elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
+       valuevftbl = o->vftbl;
+
+       /* {a is a one-dimensional array} */
+       
+       if (valuevftbl == elementvftbl)
+               return 1;
+
+       linker_classrenumber_mutex->lock();
+
+       diffval = valuevftbl->baseval - elementvftbl->baseval;
+       result  = diffval <= (uint32_t) elementvftbl->diffval;
+
+       linker_classrenumber_mutex->unlock();
+
+       return result;
+}
+
+
+/* builtin_new *****************************************************************
+
+   Creates a new instance of class c on the heap.
+
+   RETURN VALUE:
+      pointer to the object, or NULL if no memory is available
+
+   NOTE: This builtin can be called from NATIVE code only.
+
+*******************************************************************************/
+
+java_handle_t *builtin_new(classinfo *c)
+{
+       java_handle_t *o;
+#if defined(ENABLE_RT_TIMING)
+       struct timespec time_start, time_end;
+#endif
+#if defined(ENABLE_CYCLES_STATS)
+       u8 cycles_start, cycles_end;
+#endif
+
+       RT_TIMING_GET_TIME(time_start);
+       CYCLES_STATS_GET(cycles_start);
+
+       /* is the class loaded */
+
+       assert(c->state & CLASS_LOADED);
+
+       /* check if we can instantiate this class */
+
+       if (c->flags & ACC_ABSTRACT) {
+               exceptions_throw_instantiationerror(c);
+               return NULL;
+       }
+
+       /* is the class linked */
+
+       if (!(c->state & CLASS_LINKED))
+               if (!link_class(c))
+                       return NULL;
+
+       if (!(c->state & CLASS_INITIALIZED)) {
+#if !defined(NDEBUG)
+               if (initverbose)
+                       log_message_class("Initialize class (from builtin_new): ", c);
+#endif
+
+               if (!initialize_class(c))
+                       return NULL;
+       }
+
+       o = (java_handle_t*) heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
+                                                                       c->finalizer, true);
+
+       if (!o)
+               return NULL;
+
+#if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
+       /* XXX this is only a dirty hack to make Boehm work with handles */
+
+       o = LLNI_WRAP((java_object_t *) o);
+#endif
+
+       LLNI_vftbl_direct(o) = c->vftbl;
+
+#if defined(ENABLE_THREADS)
+       LLNI_DIRECT(o)->lockword.init();
+#endif
+
+       CYCLES_STATS_GET(cycles_end);
+       RT_TIMING_GET_TIME(time_end);
+
+       CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
+       RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
+
+       return o;
+}
+
+#if defined(ENABLE_ESCAPE_REASON)
+java_handle_t *builtin_escape_reason_new(classinfo *c) {
+       print_escape_reasons();
+       return builtin_java_new(c);
+}
+#endif
+
+#if defined(ENABLE_TLH)
+java_handle_t *builtin_tlh_new(classinfo *c)
+{
+       java_handle_t *o;
+# if defined(ENABLE_RT_TIMING)
+       struct timespec time_start, time_end;
+# endif
+# if defined(ENABLE_CYCLES_STATS)
+       u8 cycles_start, cycles_end;
+# endif
+
+       RT_TIMING_GET_TIME(time_start);
+       CYCLES_STATS_GET(cycles_start);
+
+       /* is the class loaded */
+
+       assert(c->state & CLASS_LOADED);
+
+       /* check if we can instantiate this class */
+
+       if (c->flags & ACC_ABSTRACT) {
+               exceptions_throw_instantiationerror(c);
+               return NULL;
+       }
+
+       /* is the class linked */
+
+       if (!(c->state & CLASS_LINKED))
+               if (!link_class(c))
+                       return NULL;
+
+       if (!(c->state & CLASS_INITIALIZED)) {
+# if !defined(NDEBUG)
+               if (initverbose)
+                       log_message_class("Initialize class (from builtin_new): ", c);
+# endif
+
+               if (!initialize_class(c))
+                       return NULL;
+       }
+
+       /*
+       o = tlh_alloc(&(THREADOBJECT->tlh), c->instancesize);
+       */
+       o = NULL;
+
+       if (o == NULL) {
+               o = (java_handle_t*) heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
+                                                                               c->finalizer, true);
+       }
+
+       if (!o)
+               return NULL;
+
+# if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
+       /* XXX this is only a dirty hack to make Boehm work with handles */
+
+       o = LLNI_WRAP((java_object_t *) o);
+# endif
+
+       LLNI_vftbl_direct(o) = c->vftbl;
+
+# if defined(ENABLE_THREADS)
+       LLNI_DIRECT(o)->lockword.init();
+# endif
+
+       CYCLES_STATS_GET(cycles_end);
+       RT_TIMING_GET_TIME(time_end);
+
+/*
+       CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
+       RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
+*/
+
+       return o;
+}
+#endif
+
+
+/* builtin_java_new ************************************************************
+
+   NOTE: This is a SLOW builtin and can be called from JIT code only.
+
+*******************************************************************************/
+
+java_handle_t *builtin_java_new(java_handle_t *clazz)
+{
+       return builtin_new(LLNI_classinfo_unwrap(clazz));
+}
+
+
+/* builtin_fast_new ************************************************************
+
+   Creates a new instance of class c on the heap.
+
+   RETURN VALUE:
+      pointer to the object, or NULL if no fast return
+      is possible for any reason.
+
+   NOTE: This is a FAST builtin and can be called from JIT code only.
+
+*******************************************************************************/
+
+java_object_t *builtin_fast_new(classinfo *c)
+{
+       java_object_t *o;
+#if defined(ENABLE_RT_TIMING)
+       struct timespec time_start, time_end;
+#endif
+#if defined(ENABLE_CYCLES_STATS)
+       u8 cycles_start, cycles_end;
+#endif
+
+       RT_TIMING_GET_TIME(time_start);
+       CYCLES_STATS_GET(cycles_start);
+
+       /* is the class loaded */
+
+       assert(c->state & CLASS_LOADED);
+
+       /* check if we can instantiate this class */
+
+       if (c->flags & ACC_ABSTRACT)
+               return NULL;
+
+       /* is the class linked */
+
+       if (!(c->state & CLASS_LINKED))
+               return NULL;
+
+       if (!(c->state & CLASS_INITIALIZED))
+               return NULL;
+
+       o = (java_handle_t*) heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
+                                                                       c->finalizer, false);
+
+       if (!o)
+               return NULL;
+
+       o->vftbl = c->vftbl;
+
+#if defined(ENABLE_THREADS)
+       LLNI_DIRECT(o)->lockword.init();
+#endif
+
+       CYCLES_STATS_GET(cycles_end);
+       RT_TIMING_GET_TIME(time_end);
+
+       CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
+       RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
+
+       return o;
+}
+
+
+/* builtin_newarray ************************************************************
+
+   Creates an array with the given vftbl on the heap. This function
+   takes as class argument an array class.
+
+   RETURN VALUE:
+      pointer to the array or NULL if no memory is available
+
+   NOTE: This builtin can be called from NATIVE code only.
+
+*******************************************************************************/
+
+java_handle_t *builtin_newarray(int32_t size, classinfo *arrayclass)
+{
+       arraydescriptor *desc;
+       s4               dataoffset;
+       s4               componentsize;
+       s4               actualsize;
+       java_handle_t   *a;
+#if defined(ENABLE_RT_TIMING)
+       struct timespec time_start, time_end;
+#endif
+
+       RT_TIMING_GET_TIME(time_start);
+
+       desc          = arrayclass->vftbl->arraydesc;
+       dataoffset    = desc->dataoffset;
+       componentsize = desc->componentsize;
+
+       if (size < 0) {
+               exceptions_throw_negativearraysizeexception();
+               return NULL;
+       }
+
+       actualsize = dataoffset + size * componentsize;
+
+       /* check for overflow */
+
+       if (((u4) actualsize) < ((u4) size)) {
+               exceptions_throw_outofmemoryerror();
+               return NULL;
+       }
+
+       a = (java_handle_t*) heap_alloc(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL, true);
+
+       if (a == NULL)
+               return NULL;
+
+#if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
+       /* XXX this is only a dirty hack to make Boehm work with handles */
+
+       a = LLNI_WRAP((java_object_t *) a);
+#endif
+
+       LLNI_vftbl_direct(a) = arrayclass->vftbl;
+
+#if defined(ENABLE_THREADS)
+       LLNI_DIRECT(a)->lockword.init();
+#endif
+
+       LLNI_array_size(a) = size;
+
+       RT_TIMING_GET_TIME(time_end);
+       RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_ARRAY);
+
+       return a;
+}
+
+
+/* builtin_java_newarray *******************************************************
+
+   NOTE: This is a SLOW builtin and can be called from JIT code only.
+
+*******************************************************************************/
+
+java_handle_t *builtin_java_newarray(int32_t size, java_handle_t *arrayclazz)
+{
+       return builtin_newarray(size, LLNI_classinfo_unwrap(arrayclazz));
+}
+
+
+/* builtin_anewarray ***********************************************************
+
+   Creates an array of references to the given class type on the heap.
+
+   RETURN VALUE:
+      pointer to the array or NULL if no memory is
+      available
+
+   NOTE: This builtin can be called from NATIVE code only.
+
+*******************************************************************************/
+
+java_handle_objectarray_t *builtin_anewarray(int32_t size, classinfo *componentclass)
+{
+       classinfo *arrayclass;
+       
+       /* is class loaded */
+
+       assert(componentclass->state & CLASS_LOADED);
+
+       /* is class linked */
+
+       if (!(componentclass->state & CLASS_LINKED))
+               if (!link_class(componentclass))
+                       return NULL;
+
+       arrayclass = class_array_of(componentclass, true);
+
+       if (!arrayclass)
+               return NULL;
+
+       return (java_handle_objectarray_t *) builtin_newarray(size, arrayclass);
+}
+
+
+/* builtin_newarray_type ****************************************************
+
+   Creates an array of [type]s on the heap.
+       
+   RETURN VALUE:
+      pointer to the array or NULL if no memory is available
+
+   NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
+
+*******************************************************************************/
+
+#define BUILTIN_NEWARRAY_TYPE(type, arraytype)                             \
+java_handle_##type##array_t *builtin_newarray_##type(int32_t size)              \
+{                                                                          \
+       return (java_handle_##type##array_t *)                                 \
+               builtin_newarray(size, primitivetype_table[arraytype].arrayclass); \
+}
+
+BUILTIN_NEWARRAY_TYPE(boolean, ARRAYTYPE_BOOLEAN)
+BUILTIN_NEWARRAY_TYPE(byte,    ARRAYTYPE_BYTE)
+BUILTIN_NEWARRAY_TYPE(char,    ARRAYTYPE_CHAR)
+BUILTIN_NEWARRAY_TYPE(short,   ARRAYTYPE_SHORT)
+BUILTIN_NEWARRAY_TYPE(int,     ARRAYTYPE_INT)
+BUILTIN_NEWARRAY_TYPE(long,    ARRAYTYPE_LONG)
+BUILTIN_NEWARRAY_TYPE(float,   ARRAYTYPE_FLOAT)
+BUILTIN_NEWARRAY_TYPE(double,  ARRAYTYPE_DOUBLE)
+
+
+/* builtin_multianewarray_intern ***********************************************
+
+   Creates a multi-dimensional array on the heap. The dimensions are
+   passed in an array of longs.
+
+   ARGUMENTS:
+      n.............number of dimensions to create
+      arrayclass....the array class
+      dims..........array containing the size of each dimension to create
+
+   RETURN VALUE:
+      pointer to the array or NULL if no memory is available
+
+******************************************************************************/
+
+static java_handle_t *builtin_multianewarray_intern(int n,
+                                                                                                       classinfo *arrayclass,
+                                                                                                       long *dims)
+{
+       s4             size;
+       java_handle_t *a;
+       classinfo     *componentclass;
+       s4             i;
+
+       /* create this dimension */
+
+       size = (s4) dims[0];
+       a = builtin_newarray(size, arrayclass);
+
+       if (!a)
+               return NULL;
+
+       /* if this is the last dimension return */
+
+       if (!--n)
+               return a;
+
+       /* get the class of the components to create */
+
+       componentclass = arrayclass->vftbl->arraydesc->componentvftbl->clazz;
+
+       /* The verifier guarantees that the dimension count is in the range. */
+
+       /* create the component arrays */
+
+       for (i = 0; i < size; i++) {
+               java_handle_t *ea =
+#if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
+                       /* we save an s4 to a s8 slot, 8-byte aligned */
+
+                       builtin_multianewarray_intern(n, componentclass, dims + 2);
+#else
+                       builtin_multianewarray_intern(n, componentclass, dims + 1);
+#endif
+
+               if (!ea)
+                       return NULL;
+
+               array_objectarray_element_set((java_handle_objectarray_t *) a, i, ea);
+       }
+
+       return a;
+}
+
+
+/* builtin_multianewarray ******************************************************
+
+   Wrapper for builtin_multianewarray_intern which checks all
+   dimensions before we start allocating.
+
+   NOTE: This is a SLOW builtin and can be called from JIT code only.
+
+******************************************************************************/
+
+java_handle_objectarray_t *builtin_multianewarray(int n,
+                                                                                                 java_handle_t *arrayclazz,
+                                                                                                 long *dims)
+{
+       classinfo *c;
+       s4         i;
+       s4         size;
+
+       /* check all dimensions before doing anything */
+
+       for (i = 0; i < n; i++) {
+#if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
+               /* we save an s4 to a s8 slot, 8-byte aligned */
+               size = (s4) dims[i * 2];
+#else
+               size = (s4) dims[i];
+#endif
+
+               if (size < 0) {
+                       exceptions_throw_negativearraysizeexception();
+                       return NULL;
+               }
+       }
+
+       c = LLNI_classinfo_unwrap(arrayclazz);
+
+       /* now call the real function */
+
+       return (java_handle_objectarray_t *)
+               builtin_multianewarray_intern(n, c, dims);
+}
+
+
+/* builtin_verbosecall_enter ***************************************************
+
+   Print method call with arguments for -verbose:call.
+
+   XXX: Remove mew once all archs use the new tracer!
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+#ifdef TRACE_ARGS_NUM
+void builtin_verbosecall_enter(s8 a0, s8 a1,
+# if TRACE_ARGS_NUM >= 4
+                                                          s8 a2, s8 a3,
+# endif
+# if TRACE_ARGS_NUM >= 6
+                                                          s8 a4, s8 a5,
+# endif
+# if TRACE_ARGS_NUM == 8
+                                                          s8 a6, s8 a7,
+# endif
+                                                          methodinfo *m)
+{
+       log_text("builtin_verbosecall_enter: Do not call me anymore!");
+}
+#endif
+#endif /* !defined(NDEBUG) */
+
+
+/* builtin_verbosecall_exit ****************************************************
+
+   Print method exit for -verbose:call.
+
+   XXX: Remove mew once all archs use the new tracer!
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m)
+{
+       log_text("builtin_verbosecall_exit: Do not call me anymore!");
+}
+#endif /* !defined(NDEBUG) */
+
+
+/*============================================================================*/
+/* MISCELLANEOUS MATHEMATICAL HELPER FUNCTIONS                                */
+/*============================================================================*/
+
+/*********** Functions for integer divisions *****************************
+       On some systems (eg. DEC ALPHA), integer division is not supported by the
+       CPU. These helper functions implement the missing functionality.
+
+******************************************************************************/
+
+#if !SUPPORT_DIVISION || defined(DISABLE_GC)
+s4 builtin_idiv(s4 a, s4 b)
+{
+       s4 c;
+
+       c = a / b;
+
+       return c;
+}
+
+s4 builtin_irem(s4 a, s4 b)
+{
+       s4 c;
+
+       c = a % b;
+
+       return c;
+}
+#endif /* !SUPPORT_DIVISION || defined(DISABLE_GC) */
+
+
+/* functions for long arithmetics **********************************************
+
+   On systems where 64 bit Integers are not supported by the CPU,
+   these functions are needed.
+
+******************************************************************************/
+
+#if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
+s8 builtin_ladd(s8 a, s8 b)
+{
+       s8 c;
+
+       c = a + b; 
+
+       return c;
+}
+
+s8 builtin_lsub(s8 a, s8 b)
+{
+       s8 c;
+
+       c = a - b; 
+
+       return c;
+}
+
+s8 builtin_lneg(s8 a)
+{
+       s8 c;
+
+       c = -a;
+
+       return c;
+}
+#endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
+
+
+#if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
+s8 builtin_lmul(s8 a, s8 b)
+{
+       s8 c;
+
+       c = a * b; 
+
+       return c;
+}
+#endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
+
+
+#if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) || defined (DISABLE_GC)
+s8 builtin_ldiv(s8 a, s8 b)
+{
+       s8 c;
+
+       c = a / b; 
+
+       return c;
+}
+
+s8 builtin_lrem(s8 a, s8 b)
+{
+       s8 c;
+
+       c = a % b; 
+
+       return c;
+}
+#endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
+
+
+#if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
+s8 builtin_lshl(s8 a, s4 b)
+{
+       s8 c;
+
+       c = a << (b & 63);
+
+       return c;
+}
+
+s8 builtin_lshr(s8 a, s4 b)
+{
+       s8 c;
+
+       c = a >> (b & 63);
+
+       return c;
+}
+
+s8 builtin_lushr(s8 a, s4 b)
+{
+       s8 c;
+
+       c = ((u8) a) >> (b & 63);
+
+       return c;
+}
+#endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
+
+
+#if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
+s8 builtin_land(s8 a, s8 b)
+{
+       s8 c;
+
+       c = a & b; 
+
+       return c;
+}
+
+s8 builtin_lor(s8 a, s8 b)
+{
+       s8 c;
+
+       c = a | b; 
+
+       return c;
+}
+
+s8 builtin_lxor(s8 a, s8 b) 
+{
+       s8 c;
+
+       c = a ^ b; 
+
+       return c;
+}
+#endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
+
+
+#if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
+s4 builtin_lcmp(s8 a, s8 b)
+{ 
+       if (a < b)
+               return -1;
+
+       if (a > b)
+               return 1;
+
+       return 0;
+}
+#endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
+
+
+/* functions for unsupported floating instructions ****************************/
+
+/* used to convert FLT_xxx defines into float values */
+
+static inline float intBitsToFloat(s4 i)
+{
+       imm_union imb;
+
+       imb.i = i;
+       return imb.f;
+}
+
+
+/* used to convert DBL_xxx defines into double values */
+
+static inline float longBitsToDouble(s8 l)
+{
+       imm_union imb;
+
+       imb.l = l;
+       return imb.d;
+}
+
+
+#if !SUPPORT_FLOAT
+float builtin_fadd(float a, float b)
+{
+       if (isnanf(a)) return intBitsToFloat(FLT_NAN);
+       if (isnanf(b)) return intBitsToFloat(FLT_NAN);
+       if (finitef(a)) {
+               if (finitef(b))
+                       return a + b;
+               else
+                       return b;
+       }
+       else {
+               if (finitef(b))
+                       return a;
+               else {
+                       if (copysignf(1.0, a) == copysignf(1.0, b))
+                               return a;
+                       else
+                               return intBitsToFloat(FLT_NAN);
+               }
+       }
+}
+
+
+float builtin_fsub(float a, float b)
+{
+       return builtin_fadd(a, builtin_fneg(b));
+}
+
+
+float builtin_fmul(float a, float b)
+{
+       if (isnanf(a)) return intBitsToFloat(FLT_NAN);
+       if (isnanf(b)) return intBitsToFloat(FLT_NAN);
+       if (finitef(a)) {
+               if (finitef(b)) return a * b;
+               else {
+                       if (a == 0) return intBitsToFloat(FLT_NAN);
+                       else return copysignf(b, copysignf(1.0, b)*a);
+               }
+       }
+       else {
+               if (finitef(b)) {
+                       if (b == 0) return intBitsToFloat(FLT_NAN);
+                       else return copysignf(a, copysignf(1.0, a)*b);
+               }
+               else {
+                       return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
+               }
+       }
+}
+
+
+/* builtin_ddiv ****************************************************************
+
+   Implementation as described in VM Spec.
+
+*******************************************************************************/
+
+float builtin_fdiv(float a, float b)
+{
+       if (finitef(a)) {
+               if (finitef(b)) {
+                       /* If neither value1' nor value2' is NaN, the sign of the result */
+                       /* is positive if both values have the same sign, negative if the */
+                       /* values have different signs. */
+
+                       return a / b;
+
+               } else {
+                       if (isnanf(b)) {
+                               /* If either value1' or value2' is NaN, the result is NaN. */
+
+                               return intBitsToFloat(FLT_NAN);
+
+                       } else {
+                               /* Division of a finite value by an infinity results in a */
+                               /* signed zero, with the sign-producing rule just given. */
+
+                               /* is sign equal? */
+
+                               if (copysignf(1.0, a) == copysignf(1.0, b))
+                                       return 0.0;
+                               else
+                                       return -0.0;
+                       }
+               }
+
+       } else {
+               if (isnanf(a)) {
+                       /* If either value1' or value2' is NaN, the result is NaN. */
+
+                       return intBitsToFloat(FLT_NAN);
+
+               } else if (finitef(b)) {
+                       /* Division of an infinity by a finite value results in a signed */
+                       /* infinity, with the sign-producing rule just given. */
+
+                       /* is sign equal? */
+
+                       if (copysignf(1.0, a) == copysignf(1.0, b))
+                               return intBitsToFloat(FLT_POSINF);
+                       else
+                               return intBitsToFloat(FLT_NEGINF);
+
+               } else {
+                       /* Division of an infinity by an infinity results in NaN. */
+
+                       return intBitsToFloat(FLT_NAN);
+               }
+       }
+}
+
+
+float builtin_fneg(float a)
+{
+       if (isnanf(a)) return a;
+       else {
+               if (finitef(a)) return -a;
+               else return copysignf(a, -copysignf(1.0, a));
+       }
+}
+#endif /* !SUPPORT_FLOAT */
+
+
+#if !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP)
+s4 builtin_fcmpl(float a, float b)
+{
+       if (isnanf(a))
+               return -1;
+
+       if (isnanf(b))
+               return -1;
+
+       if (!finitef(a) || !finitef(b)) {
+               a = finitef(a) ? 0 : copysignf(1.0,     a);
+               b = finitef(b) ? 0 : copysignf(1.0, b);
+       }
+
+       if (a > b)
+               return 1;
+
+       if (a == b)
+               return 0;
+
+       return -1;
+}
+
+
+s4 builtin_fcmpg(float a, float b)
+{
+       if (isnanf(a)) return 1;
+       if (isnanf(b)) return 1;
+       if (!finitef(a) || !finitef(b)) {
+               a = finitef(a) ? 0 : copysignf(1.0, a);
+               b = finitef(b) ? 0 : copysignf(1.0, b);
+       }
+       if (a > b) return 1;
+       if (a == b) return 0;
+       return -1;
+}
+#endif /* !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP) */
+
+
+float builtin_frem(float a, float b)
+{
+       return fmodf(a, b);
+}
+
+
+/* functions for unsupported double instructions ******************************/
+
+#if !SUPPORT_DOUBLE
+double builtin_dadd(double a, double b)
+{
+       if (isnan(a)) return longBitsToDouble(DBL_NAN);
+       if (isnan(b)) return longBitsToDouble(DBL_NAN);
+       if (finite(a)) {
+               if (finite(b)) return a + b;
+               else return b;
+       }
+       else {
+               if (finite(b)) return a;
+               else {
+                       if (copysign(1.0, a)==copysign(1.0, b)) return a;
+                       else return longBitsToDouble(DBL_NAN);
+               }
+       }
+}
+
+
+double builtin_dsub(double a, double b)
+{
+       return builtin_dadd(a, builtin_dneg(b));
+}
+
+
+double builtin_dmul(double a, double b)
+{
+       if (isnan(a)) return longBitsToDouble(DBL_NAN);
+       if (isnan(b)) return longBitsToDouble(DBL_NAN);
+       if (finite(a)) {
+               if (finite(b)) return a * b;
+               else {
+                       if (a == 0) return longBitsToDouble(DBL_NAN);
+                       else return copysign(b, copysign(1.0, b) * a);
+               }
+       }
+       else {
+               if (finite(b)) {
+                       if (b == 0) return longBitsToDouble(DBL_NAN);
+                       else return copysign(a, copysign(1.0, a) * b);
+               }
+               else {
+                       return copysign(a, copysign(1.0, a) * copysign(1.0, b));
+               }
+       }
+}
+
+
+/* builtin_ddiv ****************************************************************
+
+   Implementation as described in VM Spec.
+
+*******************************************************************************/
+
+double builtin_ddiv(double a, double b)
+{
+       if (finite(a)) {
+               if (finite(b)) {
+                       /* If neither value1' nor value2' is NaN, the sign of the result */
+                       /* is positive if both values have the same sign, negative if the */
+                       /* values have different signs. */
+
+                       return a / b;
+
+               } else {
+                       if (isnan(b)) {
+                               /* If either value1' or value2' is NaN, the result is NaN. */
+
+                               return longBitsToDouble(DBL_NAN);
+
+                       } else {
+                               /* Division of a finite value by an infinity results in a */
+                               /* signed zero, with the sign-producing rule just given. */
+
+                               /* is sign equal? */
+
+                               if (copysign(1.0, a) == copysign(1.0, b))
+                                       return 0.0;
+                               else
+                                       return -0.0;
+                       }
+               }
+
+       } else {
+               if (isnan(a)) {
+                       /* If either value1' or value2' is NaN, the result is NaN. */
+
+                       return longBitsToDouble(DBL_NAN);
+
+               } else if (finite(b)) {
+                       /* Division of an infinity by a finite value results in a signed */
+                       /* infinity, with the sign-producing rule just given. */
+
+                       /* is sign equal? */
+
+                       if (copysign(1.0, a) == copysign(1.0, b))
+                               return longBitsToDouble(DBL_POSINF);
+                       else
+                               return longBitsToDouble(DBL_NEGINF);
+
+               } else {
+                       /* Division of an infinity by an infinity results in NaN. */
+
+                       return longBitsToDouble(DBL_NAN);
+               }
+       }
+}
+
+
+/* builtin_dneg ****************************************************************
+
+   Implemented as described in VM Spec.
+
+*******************************************************************************/
+
+double builtin_dneg(double a)
+{
+       if (isnan(a)) {
+               /* If the operand is NaN, the result is NaN (recall that NaN has no */
+               /* sign). */
+
+               return a;
+
+       } else {
+               if (finite(a)) {
+                       /* If the operand is a zero, the result is the zero of opposite */
+                       /* sign. */
+
+                       return -a;
+
+               } else {
+                       /* If the operand is an infinity, the result is the infinity of */
+                       /* opposite sign. */
+
+                       return copysign(a, -copysign(1.0, a));
+               }
+       }
+}
+#endif /* !SUPPORT_DOUBLE */
+
+
+#if !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP)
+s4 builtin_dcmpl(double a, double b)
+{
+       if (isnan(a))
+               return -1;
+
+       if (isnan(b))
+               return -1;
+
+       if (!finite(a) || !finite(b)) {
+               a = finite(a) ? 0 : copysign(1.0, a);
+               b = finite(b) ? 0 : copysign(1.0, b);
+       }
+
+       if (a > b)
+               return 1;
+
+       if (a == b)
+               return 0;
+
+       return -1;
+}
+
+
+s4 builtin_dcmpg(double a, double b)
+{
+       if (isnan(a))
+               return 1;
+
+       if (isnan(b))
+               return 1;
+
+       if (!finite(a) || !finite(b)) {
+               a = finite(a) ? 0 : copysign(1.0, a);
+               b = finite(b) ? 0 : copysign(1.0, b);
+       }
+
+       if (a > b)
+               return 1;
+
+       if (a == b)
+               return 0;
+
+       return -1;
+}
+#endif /* !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP) */
+
+
+double builtin_drem(double a, double b)
+{
+       return fmod(a, b);
+}
+
+
+/* conversion operations ******************************************************/
+
+#if !(SUPPORT_FLOAT && SUPPORT_I2F)
+float builtin_i2f(s4 a)
+{
+       float f = (float) a;
+       return f;
+}
+#endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
+
+
+#if !(SUPPORT_DOUBLE && SUPPORT_I2D)
+double builtin_i2d(s4 a)
+{
+       double d = (double) a;
+       return d;
+}
+#endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
+
+
+#if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
+float builtin_l2f(s8 a)
+{
+       float f = (float) a;
+       return f;
+}
+#endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
+
+
+#if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
+double builtin_l2d(s8 a)
+{
+       double d = (double) a;
+       return d;
+}
+#endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
+
+
+#if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
+s4 builtin_f2i(float a) 
+{
+       s4 i;
+
+       i = builtin_d2i((double) a);
+
+       return i;
+
+       /*      float f;
+       
+               if (isnanf(a))
+               return 0;
+               if (finitef(a)) {
+               if (a > 2147483647)
+               return 2147483647;
+               if (a < (-2147483648))
+               return (-2147483648);
+               return (s4) a;
+               }
+               f = copysignf((float) 1.0, a);
+               if (f > 0)
+               return 2147483647;
+               return (-2147483648); */
+}
+#endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
+
+
+#if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) || defined(DISABLE_GC)
+s8 builtin_f2l(float a)
+{
+       s8 l;
+
+       l = builtin_d2l((double) a);
+
+       return l;
+
+       /*      float f;
+       
+               if (finitef(a)) {
+               if (a > 9223372036854775807L)
+               return 9223372036854775807L;
+               if (a < (-9223372036854775808L))
+               return (-9223372036854775808L);
+               return (s8) a;
+               }
+               if (isnanf(a))
+               return 0;
+               f = copysignf((float) 1.0, a);
+               if (f > 0)
+               return 9223372036854775807L;
+               return (-9223372036854775808L); */
+}
+#endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
+
+
+#if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
+s4 builtin_d2i(double a) 
+{ 
+       double d;
+       
+       if (finite(a)) {
+               if (a >= 2147483647)
+                       return 2147483647;
+               if (a <= (-2147483647-1))
+                       return (-2147483647-1);
+               return (s4) a;
+       }
+       if (isnan(a))
+               return 0;
+       d = copysign(1.0, a);
+       if (d > 0)
+               return 2147483647;
+       return (-2147483647-1);
+}
+#endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
+
+
+#if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) || defined(DISABLE_GC)
+s8 builtin_d2l(double a)
+{
+       double d;
+       
+       if (finite(a)) {
+               if (a >= 9223372036854775807LL)
+                       return 9223372036854775807LL;
+               if (a <= (-9223372036854775807LL-1))
+                       return (-9223372036854775807LL-1);
+               return (s8) a;
+       }
+       if (isnan(a))
+               return 0;
+       d = copysign(1.0, a);
+       if (d > 0)
+               return 9223372036854775807LL;
+       return (-9223372036854775807LL-1);
+}
+#endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
+
+
+#if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
+double builtin_f2d(float a)
+{
+       if (finitef(a)) return (double) a;
+       else {
+               if (isnanf(a))
+                       return longBitsToDouble(DBL_NAN);
+               else
+                       return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
+       }
+}
+
+float builtin_d2f(double a)
+{
+       if (finite(a))
+               return (float) a;
+       else {
+               if (isnan(a))
+                       return intBitsToFloat(FLT_NAN);
+               else
+                       return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
+       }
+}
+#endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
+
+
+/*============================================================================*/
+/* AUTOMATICALLY REPLACED FUNCTIONS                                           */
+/*============================================================================*/
+
+/* builtin_arraycopy ***********************************************************
+
+   Builtin for java.lang.System.arraycopy.
+
+   NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
+
+*******************************************************************************/
+
+void builtin_arraycopy(java_handle_t *src, s4 srcStart,
+                                          java_handle_t *dest, s4 destStart, s4 len)
+{
+       arraydescriptor *sdesc;
+       arraydescriptor *ddesc;
+       s4               i;
+
+       if ((src == NULL) || (dest == NULL)) {
+               exceptions_throw_nullpointerexception();
+               return;
+       }
+
+       sdesc = LLNI_vftbl_direct(src)->arraydesc;
+       ddesc = LLNI_vftbl_direct(dest)->arraydesc;
+
+       if (!sdesc || !ddesc || (sdesc->arraytype != ddesc->arraytype)) {
+               exceptions_throw_arraystoreexception();
+               return;
+       }
+
+       // Check if offsets and length are positive.
+       if ((srcStart < 0) || (destStart < 0) || (len < 0)) {
+               exceptions_throw_arrayindexoutofboundsexception();
+               return;
+       }
+
+       // Check if ranges are valid.
+       if ((((uint32_t) srcStart  + (uint32_t) len) > (uint32_t) LLNI_array_size(src)) ||
+               (((uint32_t) destStart + (uint32_t) len) > (uint32_t) LLNI_array_size(dest))) {
+               exceptions_throw_arrayindexoutofboundsexception();
+               return;
+       }
+
+       // Special case.
+       if (len == 0) {
+               return;
+       }
+
+       if (sdesc->componentvftbl == ddesc->componentvftbl) {
+               /* We copy primitive values or references of exactly the same type */
+
+               s4 dataoffset = sdesc->dataoffset;
+               s4 componentsize = sdesc->componentsize;
+
+               LLNI_CRITICAL_START;
+
+               MMOVE(((u1 *) LLNI_DIRECT(dest)) + dataoffset + componentsize * destStart,
+                         ((u1 *) LLNI_DIRECT(src))  + dataoffset + componentsize * srcStart,
+                         u1, (size_t) len * componentsize);
+
+               LLNI_CRITICAL_END;
+       }
+       else {
+               /* We copy references of different type */
+
+               java_handle_objectarray_t *oas = (java_handle_objectarray_t *) src;
+               java_handle_objectarray_t *oad = (java_handle_objectarray_t *) dest;
+               if (destStart <= srcStart) {
+                       for (i = 0; i < len; i++) {
+                               java_handle_t *o;
+
+                               o = array_objectarray_element_get(oas, srcStart + i);
+
+                               if (!builtin_canstore(oad, o))
+                                       return;
+
+                               array_objectarray_element_set(oad, destStart + i, o);
+                       }
+               }
+               else {
+                       /* XXX this does not completely obey the specification!
+                          If an exception is thrown only the elements above the
+                          current index have been copied. The specification
+                          requires that only the elements *below* the current
+                          index have been copied before the throw. */
+
+                       for (i = len - 1; i >= 0; i--) {
+                               java_handle_t *o;
+
+                               o = array_objectarray_element_get(oas, srcStart + i);
+
+                               if (!builtin_canstore(oad, o))
+                                       return;
+
+                               array_objectarray_element_set(oad, destStart + i, o);
+                       }
+               }
+       }
+}
+
+
+/* builtin_nanotime ************************************************************
+
+   Return the current time in nanoseconds.
+
+*******************************************************************************/
+
+s8 builtin_nanotime(void)
+{
+       struct timeval tv;
+       s8             usecs;
+
+       if (gettimeofday(&tv, NULL) == -1)
+               vm_abort("gettimeofday failed: %s", strerror(errno));
+
+       usecs = (s8) tv.tv_sec * (1000 * 1000) + (s8) tv.tv_usec;
+
+       return usecs * 1000;
+}
+
+
+/* builtin_currenttimemillis ***************************************************
+
+   Return the current time in milliseconds.
+
+*******************************************************************************/
+
+s8 builtin_currenttimemillis(void)
+{
+       s8 msecs;
+
+       msecs = builtin_nanotime() / 1000 / 1000;
+
+       return msecs;
+}
+
+
+/* builtin_clone ***************************************************************
+
+   Function for cloning objects or arrays.
+
+   NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
+
+*******************************************************************************/
+
+java_handle_t *builtin_clone(void *env, java_handle_t *o)
+{
+       arraydescriptor *ad;
+       u4               size;
+       classinfo       *c;
+       java_handle_t   *co;                /* cloned object header               */
+
+       /* get the array descriptor */
+
+       ad = LLNI_vftbl_direct(o)->arraydesc;
+
+       /* we are cloning an array */
+
+       if (ad != NULL) {
+               size = ad->dataoffset + ad->componentsize * LLNI_array_size(o);
+        
+               co = (java_handle_t*) heap_alloc(size, (ad->arraytype == ARRAYTYPE_OBJECT), NULL, true);
+
+               if (co == NULL)
+                       return NULL;
+
+#if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
+               /* XXX this is only a dirty hack to make Boehm work with handles */
+
+               co = LLNI_WRAP((java_object_t *) co);
+#endif
+
+               LLNI_CRITICAL_START;
+
+               MCOPY(LLNI_DIRECT(co), LLNI_DIRECT(o), u1, size);
+
+#if defined(ENABLE_GC_CACAO)
+               heap_init_objectheader(LLNI_DIRECT(co), size);
+#endif
+
+#if defined(ENABLE_THREADS)
+               LLNI_DIRECT(co)->lockword.init();
+#endif
+
+               LLNI_CRITICAL_END;
+
+               return co;
+       }
+    
+    /* we are cloning a non-array */
+
+    if (!builtin_instanceof(o, class_java_lang_Cloneable)) {
+        exceptions_throw_clonenotsupportedexception();
+        return NULL;
+    }
+
+       /* get the class of the object */
+
+       LLNI_class_get(o, c);
+
+       /* create new object */
+
+    co = builtin_new(c);
+
+    if (co == NULL)
+        return NULL;
+
+       LLNI_CRITICAL_START;
+
+       MCOPY(LLNI_DIRECT(co), LLNI_DIRECT(o), u1, c->instancesize);
+
+#if defined(ENABLE_GC_CACAO)
+       heap_init_objectheader(LLNI_DIRECT(co), c->instancesize);
+#endif
+
+#if defined(ENABLE_THREADS)
+       LLNI_DIRECT(co)->lockword.init();
+#endif
+
+       LLNI_CRITICAL_END;
+
+    return co;
+}
+
+
+#if defined(ENABLE_CYCLES_STATS)
+void builtin_print_cycles_stats(FILE *file)
+{
+       fprintf(file,"builtin cylce count statistics:\n");
+
+       CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file);
+       CYCLES_STATS_PRINT(builtin_new         ,file);
+
+       fprintf(file,"\n");
+}
+#endif /* defined(ENABLE_CYCLES_STATS) */
+
+
+#if defined(ENABLE_VMLOG)
+#define NDEBUG
+#include <vmlog_cacao.c>
+#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:
+ */
diff --git a/src/vm/jit/builtin.hpp b/src/vm/jit/builtin.hpp
new file mode 100644 (file)
index 0000000..3a7747d
--- /dev/null
@@ -0,0 +1,352 @@
+/* src/vm/jit/builtin.hpp - prototypes of builtin 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 _BUILTIN_HPP
+#define _BUILTIN_HPP
+
+/* forward typedefs ***********************************************************/
+
+typedef struct builtintable_entry builtintable_entry;
+
+#include "config.h"
+#include "vm/types.h"
+
+#include "arch.h"
+#include "md-abi.h"
+
+#include "toolbox/logging.h"
+
+#include "vm/descriptor.h"
+#include "vm/utf8.h"
+
+
+/* define infinity for floating point numbers */
+
+#define FLT_NAN     0x7fc00000
+#define FLT_POSINF  0x7f800000
+#define FLT_NEGINF  0xff800000
+
+/* define infinity for double floating point numbers */
+
+#define DBL_NAN     0x7ff8000000000000LL
+#define DBL_POSINF  0x7ff0000000000000LL
+#define DBL_NEGINF  0xfff0000000000000LL
+
+
+/* float versions are not defined in GNU classpath's fdlibm */
+
+#define copysignf    copysign
+#define finitef      finite
+#define fmodf        fmod
+#define isnanf       isnan
+
+
+/* builtin functions table ****************************************************/
+
+struct builtintable_entry {
+       s4           opcode;                /* opcode which is replaced           */
+       u4           flags;                 /* e.g. check for exception           */
+       functionptr  fp;                    /* function pointer of builtin        */
+       u1          *stub;                  /* pointer to builtin stub code       */
+       const char*  cclassname;            /* char name of the class             */
+       const char*  cname;                 /* char name of the function          */
+       const char*  cdescriptor;           /* char name of the descriptor        */
+       utf         *classname;             /* class of the function              */
+       utf         *name;                  /* name of the function               */
+       utf         *descriptor;            /* descriptor of the function         */
+       methoddesc  *md;
+};
+
+
+/* builtin table flag defines *************************************************/
+
+#define BUILTINTABLE_FLAG_STUB         0x0001 /* builtin needs a stub         */
+#define BUILTINTABLE_FLAG_EXCEPTION    0x0002 /* check for excepion on return */
+
+
+/* function prototypes ********************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool builtin_init(void);
+
+s4                                     builtintable_get_key(builtintable_entry *);
+builtintable_entry *builtintable_get_by_key(s4 key);
+builtintable_entry *builtintable_get_internal(functionptr fp);
+builtintable_entry *builtintable_get_automatic(s4 opcode);
+
+bool builtintable_replace_function(void *iptr);
+
+
+/**********************************************************************/
+/* BUILTIN FUNCTIONS                                                  */
+/**********************************************************************/
+
+/* NOTE: Builtin functions which are used in the BUILTIN* opcodes must
+ * have a BUILTIN_... macro defined as seen below. In code dealing
+ * with the BUILTIN* opcodes the functions may only be addressed by
+ * these macros, never by their actual name! (This helps to make this
+ * code more portable.)
+ *
+ * C and assembler code which does not deal with the BUILTIN* opcodes,
+ * can use the builtin functions normally (like all other functions).
+ *
+ * IMPORTANT:
+ * For each builtin function which is used in a BUILTIN* opcode there
+ * must be an entry in the tables in vm/builtintable.inc.
+ *
+ * Below each prototype is either the BUILTIN_ macro definition or a
+ * comment specifiying that this function is not used in BUILTIN*
+ * opcodes.
+ *
+ * (The BUILTIN* opcodes are ICMD_BUILTIN1, ICMD_BUILTIN2 and
+ * ICMD_BUILTIN3.)
+ */
+
+bool builtin_instanceof(java_handle_t *obj, classinfo *c);
+/* NOT AN OP */
+bool builtin_checkcast(java_handle_t *obj, classinfo *c);
+/* NOT AN OP */
+bool builtin_arrayinstanceof(java_handle_t *h, classinfo *targetclass);
+/* NOT AN OP */
+bool builtin_fast_arrayinstanceof(java_object_t *o, classinfo *targetclass);
+#define BUILTIN_arrayinstanceof (functionptr) builtin_fast_arrayinstanceof
+bool builtin_fast_arraycheckcast(java_object_t *o, classinfo *targetclass);
+#define BUILTIN_arraycheckcast (functionptr) builtin_fast_arraycheckcast
+
+bool builtin_canstore(java_handle_objectarray_t *oa, java_handle_t *o);
+/* NOT AN OP */
+bool builtin_fast_canstore(java_objectarray_t *oa, java_object_t *o);
+#define BUILTIN_FAST_canstore (functionptr) builtin_fast_canstore
+
+void *builtin_throw_exception(java_object_t *exception);
+/* NOT AN OP */
+java_object_t *builtin_retrieve_exception(void);
+/* NOT AN OP */
+
+java_handle_t *builtin_new(classinfo *c);
+/* NOT AN OP */
+java_handle_t *builtin_java_new(java_handle_t *c);
+#define BUILTIN_new (functionptr) builtin_java_new
+
+#if defined(ENABLE_TLH)
+#define BUILTIN_tlh_new (functionptr) builtin_tlh_new
+java_handle_t *builtin_tlh_new(classinfo *c);
+#endif
+
+#if defined(ENABLE_ESCAPE_REASON)
+#define BUILTIN_escape_reason_new (functionptr)builtin_escape_reason_new
+java_handle_t *builtin_escape_reason_new(classinfo *c);
+#endif
+
+java_object_t *builtin_fast_new(classinfo *c);
+#define BUILTIN_FAST_new (functionptr) builtin_fast_new
+
+java_handle_t *builtin_newarray(int32_t size, classinfo *arrayclass);
+/* NOT AN OP */
+java_handle_t *builtin_java_newarray(int32_t size, java_handle_t *arrayclass);
+#define BUILTIN_newarray (functionptr) builtin_java_newarray
+
+java_handle_objectarray_t *builtin_anewarray(int32_t size, classinfo *componentclass);
+/* NOT AN OP */
+
+java_handle_booleanarray_t *builtin_newarray_boolean(int32_t size);
+#define BUILTIN_newarray_boolean (functionptr) builtin_newarray_boolean
+java_handle_chararray_t *builtin_newarray_char(int32_t size);
+#define BUILTIN_newarray_char (functionptr) builtin_newarray_char
+java_handle_floatarray_t *builtin_newarray_float(int32_t size);
+#define BUILTIN_newarray_float (functionptr) builtin_newarray_float
+java_handle_doublearray_t *builtin_newarray_double(int32_t size);
+#define BUILTIN_newarray_double (functionptr) builtin_newarray_double
+java_handle_bytearray_t *builtin_newarray_byte(int32_t size);
+#define BUILTIN_newarray_byte (functionptr) builtin_newarray_byte
+java_handle_shortarray_t *builtin_newarray_short(int32_t size);
+#define BUILTIN_newarray_short (functionptr) builtin_newarray_short
+java_handle_intarray_t *builtin_newarray_int(int32_t size);
+#define BUILTIN_newarray_int (functionptr) builtin_newarray_int
+java_handle_longarray_t *builtin_newarray_long(int32_t size);
+#define BUILTIN_newarray_long (functionptr) builtin_newarray_long
+
+java_handle_objectarray_t *builtin_multianewarray(int n,
+                                                                                                 java_handle_t *arrayclass,
+                                                                                                 long *dims);
+#define BUILTIN_multianewarray (functionptr) builtin_multianewarray
+
+#if defined(TRACE_ARGS_NUM)
+void builtin_verbosecall_enter(s8 a0, s8 a1,
+# if TRACE_ARGS_NUM >= 4
+                                                          s8 a2, s8 a3,
+# endif
+# if TRACE_ARGS_NUM >= 6
+                                                          s8 a4, s8 a5,
+# endif
+# if TRACE_ARGS_NUM == 8
+                                                          s8 a6, s8 a7,
+# endif
+                                                          methodinfo *m);
+/* NOT AN OP */
+#endif /* defined(TRACE_ARGS_NUM) */
+
+void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m);
+/* NOT AN OP */
+
+s4 builtin_idiv(s4 a, s4 b);
+#define BUILTIN_idiv (functionptr) builtin_idiv
+s4 builtin_irem(s4 a, s4 b);
+#define BUILTIN_irem (functionptr) builtin_irem
+
+s8 builtin_ladd(s8 a, s8 b);
+#define BUILTIN_ladd (functionptr) builtin_ladd
+s8 builtin_lsub(s8 a, s8 b);
+#define BUILTIN_lsub (functionptr) builtin_lsub
+s8 builtin_lmul(s8 a, s8 b);
+#define BUILTIN_lmul (functionptr) builtin_lmul
+
+s8 builtin_ldiv(s8 a, s8 b);
+#define BUILTIN_ldiv (functionptr) builtin_ldiv
+s8 builtin_lrem(s8 a, s8 b);
+#define BUILTIN_lrem (functionptr) builtin_lrem
+
+s8 builtin_lshl(s8 a, s4 b);
+#define BUILTIN_lshl (functionptr) builtin_lshl
+s8 builtin_lshr(s8 a, s4 b);
+#define BUILTIN_lshr (functionptr) builtin_lshr
+s8 builtin_lushr(s8 a, s4 b);
+#define BUILTIN_lushr (functionptr) builtin_lushr
+s8 builtin_land(s8 a, s8 b);
+#define BUILTIN_land (functionptr) builtin_land
+s8 builtin_lor(s8 a, s8 b);
+#define BUILTIN_lor (functionptr) builtin_lor
+s8 builtin_lxor(s8 a, s8 b);
+#define BUILTIN_lxor (functionptr) builtin_lxor
+s8 builtin_lneg(s8 a);
+#define BUILTIN_lneg (functionptr) builtin_lneg
+s4 builtin_lcmp(s8 a, s8 b);
+#define BUILTIN_lcmp (functionptr) builtin_lcmp
+
+float builtin_fadd(float a, float b);
+#define BUILTIN_fadd (functionptr) builtin_fadd
+float builtin_fsub(float a, float b);
+#define BUILTIN_fsub (functionptr) builtin_fsub
+float builtin_fmul(float a, float b);
+#define BUILTIN_fmul (functionptr) builtin_fmul
+float builtin_fdiv(float a, float b);
+#define BUILTIN_fdiv (functionptr) builtin_fdiv
+float builtin_fneg(float a);         
+#define BUILTIN_fneg (functionptr) builtin_fneg
+s4 builtin_fcmpl(float a, float b);  
+#define BUILTIN_fcmpl (functionptr) builtin_fcmpl
+s4 builtin_fcmpg(float a, float b);  
+#define BUILTIN_fcmpg (functionptr) builtin_fcmpg
+float builtin_frem(float a, float b);
+#define BUILTIN_frem (functionptr) builtin_frem
+
+double builtin_dadd(double a, double b);
+#define BUILTIN_dadd (functionptr) builtin_dadd
+double builtin_dsub(double a, double b);
+#define BUILTIN_dsub (functionptr) builtin_dsub
+double builtin_dmul(double a, double b);
+#define BUILTIN_dmul (functionptr) builtin_dmul
+double builtin_ddiv(double a, double b);
+#define BUILTIN_ddiv (functionptr) builtin_ddiv
+double builtin_dneg(double a);          
+#define BUILTIN_dneg (functionptr) builtin_dneg
+s4 builtin_dcmpl(double a, double b);   
+#define BUILTIN_dcmpl (functionptr) builtin_dcmpl
+s4 builtin_dcmpg(double a, double b);   
+#define BUILTIN_dcmpg (functionptr) builtin_dcmpg
+double builtin_drem(double a, double b);
+#define BUILTIN_drem (functionptr) builtin_drem
+
+float    builtin_i2f(s4 i);
+#define BUILTIN_i2f (functionptr) builtin_i2f
+double   builtin_i2d(s4 i);
+#define BUILTIN_i2d (functionptr) builtin_i2d
+float    builtin_l2f(s8 l);
+#define BUILTIN_l2f (functionptr) builtin_l2f
+double   builtin_l2d(s8 l);
+#define BUILTIN_l2d (functionptr) builtin_l2d
+
+s4       builtin_f2i(float a);
+#define BUILTIN_f2i (functionptr) builtin_f2i
+s4       asm_builtin_f2i(float a);
+/* NOT AN OP */
+s8       builtin_f2l(float a);
+#define BUILTIN_f2l (functionptr) builtin_f2l
+s8       asm_builtin_f2l(float a);
+/* NOT AN OP */
+
+double   builtin_f2d(float a);
+#define BUILTIN_f2d (functionptr) builtin_f2d
+
+s4       builtin_d2i(double a);
+#define BUILTIN_d2i (functionptr) builtin_d2i
+s4       asm_builtin_d2i(double a);
+/* NOT AN OP */
+s8       builtin_d2l(double a);
+#define BUILTIN_d2l (functionptr) builtin_d2l
+s8       asm_builtin_d2l(double a);
+/* NOT AN OP */
+
+float    builtin_d2f(double a);
+#define BUILTIN_d2f (functionptr) builtin_d2f
+
+java_handle_t *builtin_clone(void *env, java_handle_t *o);
+#define BUILTIN_clone (functionptr) builtin_clone
+
+void builtin_arraycopy(java_handle_t *src, s4 srcStart,
+                                          java_handle_t *dest, s4 destStart, s4 len);
+#define BUILTIN_arraycopy (functionptr) builtin_arraycopy
+
+s8 builtin_nanotime(void);
+s8 builtin_currenttimemillis(void);
+#define BUILTIN_currenttimemillis (functionptr) builtin_currenttimemillis
+
+#if defined(ENABLE_CYCLES_STATS)
+void builtin_print_cycles_stats(FILE *file);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _BUILTIN_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:
+ */
diff --git a/src/vm/jit/builtintable.inc b/src/vm/jit/builtintable.inc
new file mode 100644 (file)
index 0000000..30807db
--- /dev/null
@@ -0,0 +1,1108 @@
+/* src/vm/jit/builtintable.inc - tables of builtin 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 "arch.h"
+
+#include "threads/lock.hpp"
+
+#include "vm/jit/builtin.hpp"
+#include "vm/jit/jit.hpp"
+
+
+/* internal and not automatically replaced functions **************************/
+
+static builtintable_entry builtintable_internal[] = {
+
+#if defined(__ALPHA__) || defined(DISABLE_GC)
+       {
+               ICMD_F2L,
+               0,
+               BUILTIN_f2l,
+               NULL,
+               NULL,
+               "f2l",
+               "(F)J",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+       {
+               ICMD_D2L,
+               0,
+               BUILTIN_d2l,
+               NULL,
+               NULL,
+               "d2l",
+               "(D)J",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+       {
+               ICMD_F2I,
+               0,
+               BUILTIN_f2i,
+               NULL,
+               NULL,
+               "f2i",
+               "(F)I",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+       {
+               ICMD_D2I,
+               0,
+               BUILTIN_d2i,
+               NULL,
+               NULL,
+               "d2i",
+               "(D)I",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+#endif
+
+#if !SUPPORT_DIVISION || defined(DISABLE_GC)
+       {
+               ICMD_IDIV,
+               0,
+               BUILTIN_idiv,
+               NULL,
+               NULL,
+               "idiv",
+               "(II)I",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+       {
+               ICMD_IREM,
+               0,
+               BUILTIN_irem,
+               NULL,
+               NULL,
+               "irem",
+               "(II)I",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+#endif
+
+#if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) || defined(DISABLE_GC)
+       {
+               ICMD_LDIV,
+               0,
+               BUILTIN_ldiv,
+               NULL,
+               NULL,
+               "ldiv",
+               "(JJ)J",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+       {
+               ICMD_LREM,
+               0,
+               BUILTIN_lrem,
+               NULL,
+               NULL,
+               "lrem",
+               "(JJ)J",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+#endif
+
+       {
+               ICMD_FREM,
+               0,
+               BUILTIN_frem,
+               NULL,
+               NULL,
+               "frem",
+               "(FF)F",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+       {
+               ICMD_DREM,
+               0,
+               BUILTIN_drem,
+               NULL,
+               NULL,
+               "drem",
+               "(DD)D",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+
+
+       /* internal functions *****************************************************/
+
+       {
+               ICMD_NEW,
+               BUILTINTABLE_FLAG_STUB,
+               BUILTIN_new,
+               NULL,
+               NULL,
+               "new",
+               "(Ljava/lang/Class;)Ljava/lang/Object;",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+
+#if defined(ENABLE_TLH)
+       {
+               ICMD_NEW,
+               BUILTINTABLE_FLAG_STUB,
+               BUILTIN_tlh_new,
+               NULL,
+               NULL,
+               "tlh_new",
+               "(Ljava/lang/Class;)Ljava/lang/Object;",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+#endif
+
+#if defined(ENABLE_ESCAPE_REASON)
+       {
+               ICMD_NEW,
+               BUILTINTABLE_FLAG_STUB,
+               BUILTIN_escape_reason_new,
+               NULL,
+               NULL,
+               "escape_reason_new",
+               "(Ljava/lang/Class;)Ljava/lang/Object;",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+#endif
+
+       {
+               ICMD_NEW,
+               0,
+               BUILTIN_FAST_new,
+               NULL,
+               NULL,
+               "fast-new",
+               "(Ljava/lang/Class;)Ljava/lang/Object;",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+       {
+               ICMD_ANEWARRAY,
+               BUILTINTABLE_FLAG_STUB,
+               BUILTIN_newarray,
+               NULL,
+               NULL,
+               "newarray",
+               "(ILjava/lang/Class;)[Ljava/lang/Object;",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+       {
+               ICMD_NEWARRAY,
+               BUILTINTABLE_FLAG_STUB,
+               BUILTIN_newarray_boolean,
+               NULL,
+               NULL,
+               "newarray_boolean",
+               "(I)[Z",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+       {
+               ICMD_NEWARRAY,
+               BUILTINTABLE_FLAG_STUB,
+               BUILTIN_newarray_byte,
+               NULL,
+               NULL,
+               "newarray_byte",
+               "(I)[B",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+       {
+               ICMD_NEWARRAY,
+               BUILTINTABLE_FLAG_STUB,
+               BUILTIN_newarray_char,
+               NULL,
+               NULL,
+               "newarray_char",
+               "(I)[C",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+       {
+               ICMD_NEWARRAY,
+               BUILTINTABLE_FLAG_STUB,
+               BUILTIN_newarray_short,
+               NULL,
+               NULL,
+               "newarray_short",
+               "(I)[S",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+       {
+               ICMD_NEWARRAY,
+               BUILTINTABLE_FLAG_STUB,
+               BUILTIN_newarray_int,
+               NULL,
+               NULL,
+               "newarray_int",
+               "(I)[I",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+       {
+               ICMD_NEWARRAY,
+               BUILTINTABLE_FLAG_STUB,
+               BUILTIN_newarray_long,
+               NULL,
+               NULL,
+               "newarray_long",
+               "(I)[J",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+       {
+               ICMD_NEWARRAY,
+               BUILTINTABLE_FLAG_STUB,
+               BUILTIN_newarray_float,
+               NULL,
+               NULL,
+               "newarray_float",
+               "(I)[F",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+       {
+               ICMD_NEWARRAY,
+               BUILTINTABLE_FLAG_STUB,
+               BUILTIN_newarray_double,
+               NULL,
+               NULL,
+               "newarray_double",
+               "(I)[D",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+       {
+               ICMD_MULTIANEWARRAY,
+               BUILTINTABLE_FLAG_STUB,
+               BUILTIN_multianewarray,
+               NULL,
+               NULL,
+               "multianewarray",
+               /* XXX it should be: "(ILjava/lang/Class;[I)[Ljava/lang/Object;", */
+               "(ILjava/lang/Class;I)[Ljava/lang/Object;",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+       {
+               ICMD_CHECKCAST,
+               0,
+               BUILTIN_arraycheckcast,
+               NULL,
+               NULL,
+               "arraycheckcast",
+               "([Ljava/lang/Object;[Ljava/lang/Object;)[Ljava/lang/Object;",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+       {
+               ICMD_INSTANCEOF,
+               0,
+               BUILTIN_arrayinstanceof,
+               NULL,
+               NULL,
+               "arrayinstanceof",
+               "([Ljava/lang/Object;[Ljava/lang/Object;)I",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+       {
+               ICMD_AASTORE,
+               0,
+               BUILTIN_FAST_canstore,
+               NULL,
+               NULL,
+               "fast-canstore",
+               "([Ljava/lang/Object;Ljava/lang/Object;)I",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+
+#if defined(ENABLE_THREADS)
+       {
+               ICMD_MONITORENTER,
+               BUILTINTABLE_FLAG_STUB,
+               LOCK_monitor_enter,
+               NULL,
+               NULL,
+               "monitorenter",
+               "(Ljava/lang/Object;)V",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+       {
+               ICMD_MONITOREXIT,
+               BUILTINTABLE_FLAG_STUB,
+               LOCK_monitor_exit,
+               NULL,
+               NULL,
+               "monitorexit",
+               "(Ljava/lang/Object;)V",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+#endif
+
+
+       /* stop entry */
+
+       {
+               255,
+               0,
+               NULL,
+               NULL,
+               NULL,
+               NULL,
+               NULL,
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+};
+
+
+/* automatically replaced functions *******************************************/
+
+static builtintable_entry builtintable_automatic[] = {
+
+#if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
+       {
+               ICMD_LCMP,
+               0,
+               BUILTIN_lcmp,
+               NULL,
+               NULL,
+               "lcmp",
+               "(JJ)I",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+#endif
+
+#if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
+       {
+               ICMD_LAND,
+               0,
+               BUILTIN_land,
+               NULL,
+               NULL,
+               "land",
+               "(JJ)J",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+       {
+               ICMD_LOR,
+               0,
+               BUILTIN_lor,
+               NULL,
+               NULL,
+               "lor",
+               "(JJ)J",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+       {
+               ICMD_LXOR,
+               0,
+               BUILTIN_lxor,
+               NULL,
+               NULL,
+               "lxor",
+               "(JJ)J",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+#endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
+
+#if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
+       {
+               ICMD_LSHL,
+               0,
+               BUILTIN_lshl,
+               NULL,
+               NULL,
+               "lshl",
+               "(JI)J",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+       {
+               ICMD_LSHR,
+               0,
+               BUILTIN_lshr,
+               NULL,
+               NULL,
+               "lshr",
+               "(JI)J",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+       {
+               ICMD_LUSHR,
+               0,
+               BUILTIN_lushr,
+               NULL,
+               NULL,
+               "lushr",
+               "(JI)J",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+#endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
+
+#if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
+       {
+               ICMD_LADD,
+               0,
+               BUILTIN_ladd,
+               NULL,
+               NULL,
+               "ladd",
+               "(JJ)J",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+       {
+               ICMD_LSUB,
+               0,
+               BUILTIN_lsub,
+               NULL,
+               NULL,
+               "lsub",
+               "(JJ)J",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+       {
+               ICMD_LNEG,
+               0,
+               BUILTIN_lneg,
+               NULL,
+               NULL,
+               "lneg",
+               "(J)J",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+#endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
+
+#if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
+       {
+               ICMD_LMUL,
+               0,
+               BUILTIN_lmul,
+               NULL,
+               NULL,
+               "lmul",
+               "(JJ)J",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+#endif
+
+#if !(SUPPORT_FLOAT && SUPPORT_I2F)
+       {
+               ICMD_I2F,
+               0,
+               BUILTIN_i2f,
+               NULL,
+               NULL,
+               "i2f",
+               "(I)F",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+#endif
+
+#if !(SUPPORT_DOUBLE && SUPPORT_I2D)
+       {
+               ICMD_I2D,
+               0,
+               BUILTIN_i2d,
+               NULL,
+               NULL,
+               "i2d",
+               "(I)D",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+#endif
+
+#if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
+       {
+               ICMD_L2F,
+               0,
+               BUILTIN_l2f,
+               NULL,
+               NULL,
+               "l2f",
+               "(J)F",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+#endif
+
+#if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
+       {
+               ICMD_L2D,
+               0,
+               BUILTIN_l2d,
+               NULL,
+               NULL,
+               "l2d",
+               "(J)D",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+#endif
+
+#if !(SUPPORT_FLOAT && SUPPORT_F2I)
+       {
+               ICMD_F2I,
+               0,
+               BUILTIN_f2i,
+               NULL,
+               NULL,
+               "f2i",
+               "(F)I",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+#endif
+
+#if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L)
+       {
+               ICMD_F2L,
+               0,
+               BUILTIN_f2l,
+               NULL,
+               NULL,
+               "f2l",
+               "(F)J",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+#endif
+
+#if !(SUPPORT_DOUBLE && SUPPORT_D2I)
+       {
+               ICMD_D2I,
+               0,
+               BUILTIN_d2i,
+               NULL,
+               NULL,
+               "d2i",
+               "(D)I",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+#endif
+
+#if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L)
+       {
+               ICMD_D2L,
+               0,
+               BUILTIN_d2l,
+               NULL,
+               NULL,
+               "d2l",
+               "(D)J",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+#endif
+
+
+       /* float functions ********************************************************/
+
+#if !SUPPORT_FLOAT
+       {
+               ICMD_FADD,
+               0,
+               BUILTIN_fadd,
+               NULL,
+               NULL,
+               "fadd",
+               "(FF)F",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+       {
+               ICMD_FSUB,
+               0,
+               BUILTIN_fsub,
+               NULL,
+               NULL,
+               "fsub",
+               "(FF)F",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+       {
+               ICMD_FMUL,
+               0,
+               BUILTIN_fmul,
+               NULL,
+               NULL,
+               "fmul",
+               "(FF)F",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+       {
+               ICMD_FDIV,
+               0,
+               BUILTIN_fdiv,
+               NULL,
+               NULL,
+               "fdiv",
+               "(FF)F",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+       {
+               ICMD_FNEG,
+               0,
+               BUILTIN_fneg,
+               NULL,
+               NULL,
+               "fneg",
+               "(F)F",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+#endif /* !SUPPORT_FLOAT */
+
+#if !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP
+       {
+               ICMD_FCMPL,
+               0,
+               BUILTIN_fcmpl,
+               NULL,
+               NULL,
+               "fcmpl",
+               "(FF)I",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+       {
+               ICMD_FCMPG,
+               0,
+               BUILTIN_fcmpg,
+               NULL,
+               NULL,
+               "fcmpg",
+               "(FF)I",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+#endif /* !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP */
+
+
+       /* double functions *******************************************************/
+
+#if !SUPPORT_DOUBLE
+       {
+               ICMD_DADD,
+               0,
+               BUILTIN_dadd,
+               NULL,
+               NULL,
+               "dadd",
+               "(DD)D",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+       {
+               ICMD_DSUB,
+               0,
+               BUILTIN_dsub,
+               NULL,
+               NULL,
+               "dsub",
+               "(DD)D",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+       {
+               ICMD_DMUL,
+               0,
+               BUILTIN_dmul,
+               NULL,
+               NULL,
+               "dmul",
+               "(DD)D",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+       {
+               ICMD_DDIV,
+               0,
+               BUILTIN_ddiv,
+               NULL,
+               NULL,
+               "ddiv",
+               "(DD)D",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+       {
+               ICMD_DNEG,
+               0,
+               BUILTIN_dneg,
+               NULL,
+               NULL,
+               "dneg",
+               "(D)D",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+#endif /* !SUPPORT_DOUBLE */
+
+#if !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP
+       {
+               ICMD_DCMPL,
+               0,
+               BUILTIN_dcmpl,
+               NULL,
+               NULL,
+               "dcmpl",
+               "(DD)I",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+       {
+               ICMD_DCMPG,
+               0,
+               BUILTIN_dcmpg,
+               NULL,
+               NULL,
+               "dcmpg",
+               "(DD)I",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+#endif /* !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP */
+
+
+       /* float/double functions *************************************************/
+
+#if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
+       {
+               ICMD_F2D,
+               0,
+               BUILTIN_f2d,
+               NULL,
+               NULL,
+               "f2d",
+               "(F)D",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+       {
+               ICMD_D2F,
+               0,
+               BUILTIN_d2f,
+               NULL,
+               NULL,
+               "d2f",
+               "(D)F",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+#endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
+
+
+       /* prevent a compiler warning if everything is supported (e.g. i386) */
+
+       {
+               255,
+               0,
+               NULL,
+               NULL,
+               NULL,
+               NULL,
+               NULL,
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+};
+
+
+/* automatically replaced functions *******************************************/
+
+static builtintable_entry builtintable_function[] = {
+#if defined(ENABLE_JIT)
+
+       /* java.lang.VMSystem.arraycopy(Ljava/lang/Object;ILjava/lang/Object;II)V STATIC NATIVE */
+
+       {
+               ICMD_BUILTIN,
+               BUILTINTABLE_FLAG_STUB | BUILTINTABLE_FLAG_EXCEPTION,
+               BUILTIN_arraycopy,
+               NULL,
+               "java/lang/VMSystem",
+               "arraycopy",
+               "(Ljava/lang/Object;ILjava/lang/Object;II)V",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+
+       /* java.lang.System.arraycopy(Ljava/lang/Object;ILjava/lang/Object;II)V PUBLIC STATIC */
+
+#if 0
+       /* We disable this one until we have a fix for the stacktrace
+          issue. */
+
+       {
+               ICMD_BUILTIN,
+               BUILTINTABLE_FLAG_STUB | BUILTINTABLE_FLAG_EXCEPTION,
+               BUILTIN_arraycopy,
+               NULL,
+               "java/lang/System",
+               "arraycopy",
+               "(Ljava/lang/Object;ILjava/lang/Object;II)V",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+#endif
+
+       /* java.lang.VMSystem.currentTimeMillis()J PUBLIC STATIC */
+
+       {
+               ICMD_BUILTIN,
+               0,
+               BUILTIN_currenttimemillis,
+               NULL,
+               "java/lang/VMSystem",
+               "currentTimeMillis",
+               "()J",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+
+       /* java.lang.System.currentTimeMillis()J PUBLIC STATIC */
+
+       {
+               ICMD_BUILTIN,
+               0,
+               BUILTIN_currenttimemillis,
+               NULL,
+               "java/lang/System",
+               "currentTimeMillis",
+               "()J",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+
+#endif /* defined(ENABLE_JIT) */
+
+       /* stop entry */
+
+       {
+               255,
+               0,
+               NULL,
+               NULL,
+               NULL,
+               NULL,
+               NULL,
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+};
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
index da46ee966b02b3beadb2ee23c3391c9a4e7f89dc..4772b95f2f71d984b7cb776122ff305233e7527e 100644 (file)
@@ -34,7 +34,7 @@
 
 #include "vm/global.h"
 
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
 #include "vm/jit/stack.h"
 
 
index a82b75ad7036f4b3a9ed619c013743f642712df8..a9d787a11a05242913f5b55c1beee45bcd0c5886 100644 (file)
@@ -1,9 +1,7 @@
 /* src/vm/jit/cfg.h - build a control-flow graph
 
-   Copyright (C) 2006, 2007 R. Grafl, A. Krall, C. Kruegel, C. Oates,
-   R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
-   C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
-   J. Wenninger, Institut f. Computersprachen - TU Wien
+   Copyright (C) 2006, 2007, 2008
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
 
@@ -32,7 +30,7 @@
 
 #include "vm/global.h"
 
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
 
 
 /* defines ********************************************************************/
 
 /* function prototypes ********************************************************/
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 bool cfg_build(jitdata *jd);
 
 void cfg_add_root(jitdata *jd);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* _CFG_H */
 
 
diff --git a/src/vm/jit/code.c b/src/vm/jit/code.c
deleted file mode 100644 (file)
index b3a2aff..0000000
+++ /dev/null
@@ -1,305 +0,0 @@
-/* src/vm/jit/code.c - codeinfo struct for representing compiled 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.
-
-*/
-
-
-#include "config.h"
-
-#include <assert.h>
-#include <stdint.h>
-
-#include "arch.h"
-
-#include "mm/memory.h"
-
-#include "vm/options.h"
-#include "vm/vm.hpp"
-
-#include "vm/jit/code.h"
-#include "vm/jit/codegen-common.h"
-#include "vm/jit/jitcache.hpp"
-#include "vm/jit/methodtree.h"
-#include "vm/jit/patcher-common.h"
-
-
-/* code_init *******************************************************************
-
-   Initialize the code-subsystem.
-
-*******************************************************************************/
-
-void code_init(void)
-{
-       /* Check if offset of codeinfo.m == 0 (see comment in code.h). */
-
-       if (OFFSET(codeinfo, m) != 0)
-               vm_abort("code_init: offset of codeinfo.m != 0: %d != 0", OFFSET(codeinfo, m));
-}
-
-
-/* code_codeinfo_new ***********************************************************
-
-   Create a new codeinfo for the given method.
-   
-   IN:
-       m................method to create a new codeinfo for
-
-   The following fields are set in codeinfo:
-       m
-       patchers
-          cachedrefs
-
-   RETURN VALUE:
-       a new, initialized codeinfo, or
-          NULL if an exception occurred.
-  
-*******************************************************************************/
-
-codeinfo *code_codeinfo_new(methodinfo *m)
-{
-       codeinfo *code;
-
-       code = NEW(codeinfo);
-
-       code->m = m;
-
-       patcher_list_create(code);
-
-#if defined (ENABLE_JITCACHE)
-       jitcache_list_create(code);
-#endif
-
-#if defined (ENABLE_STATISTICS)
-       if (opt_stat)
-               size_codeinfo += sizeof(codeinfo);
-#endif
-
-       return code;
-}
-
-
-/* code_find_codeinfo_for_pc ***************************************************
-
-   Return the codeinfo for the compilation unit that contains the
-   given PC.
-
-   ARGUMENTS:
-       pc...............machine code position
-
-   RETURN VALUE:
-       the codeinfo * for the given PC
-
-*******************************************************************************/
-
-codeinfo *code_find_codeinfo_for_pc(void *pc)
-{
-       void *pv;
-
-       pv = methodtree_find(pc);
-
-       return code_get_codeinfo_for_pv(pv);
-}
-
-
-/* code_find_codeinfo_for_pc ***************************************************
-
-   Return the codeinfo for the compilation unit that contains the
-   given PC. This method does not check the return value and is used
-   by the GC.
-
-   IN:
-       pc...............machine code position
-
-   RETURN VALUE:
-       the codeinfo * for the given PC, or NULL
-
-*******************************************************************************/
-
-codeinfo *code_find_codeinfo_for_pc_nocheck(void *pc)
-{
-       void *pv;
-
-       pv = methodtree_find_nocheck(pc);
-
-       if (pv == NULL)
-               return NULL;
-
-       return code_get_codeinfo_for_pv(pv);
-}
-
-
-/* code_get_methodinfo_for_pv **************************************************
-
-   Return the methodinfo for the given PV.
-
-   IN:
-       pv...............PV
-
-   RETURN VALUE:
-       the methodinfo *
-
-*******************************************************************************/
-
-methodinfo *code_get_methodinfo_for_pv(void *pv)
-{
-       codeinfo *code;
-
-       code = code_get_codeinfo_for_pv(pv);
-
-       /* This is the case for asm_vm_call_method. */
-
-       if (code == NULL)
-               return NULL;
-
-       return code->m;
-}
-
-
-/* code_get_sync_slot_count ****************************************************
-
-   Return the number of stack slots used for storing the synchronized object
-   (and the return value around lock_monitor_exit calls) by the given code.
-   
-   IN:
-       code.............the codeinfo of the code in question
-                           (must be != NULL)
-
-   RETURN VALUE:
-       the number of stack slots used for synchronization
-  
-*******************************************************************************/
-
-#if defined(ENABLE_REPLACEMENT)
-int code_get_sync_slot_count(codeinfo *code)
-{
-#ifdef ENABLE_THREADS
-       int count;
-       
-       assert(code);
-
-       if (!checksync)
-               return 0;
-
-       if (!code_is_synchronized(code))
-               return 0;
-
-       count = 1;
-
-#ifdef HAS_4BYTE_STACKSLOT
-       /* long and double need 2 4-byte slots */
-       if (IS_2_WORD_TYPE(code->m->parseddesc->returntype.type))
-               count++;
-#endif
-
-#if defined(__POWERPC__)
-       /* powerpc needs an extra slot */
-       count++;
-#endif
-
-       return count;
-
-#else /* !ENABLE_THREADS */
-       
-       return 0;
-
-#endif /* ENABLE_THREADS */
-}
-#endif /* defined(ENABLE_REPLACEMENT) */
-
-
-/* code_codeinfo_free **********************************************************
-
-   Free the memory used by a codeinfo.
-   
-   IN:
-       code.............the codeinfo to free
-
-*******************************************************************************/
-
-void code_codeinfo_free(codeinfo *code)
-{
-       if (code == NULL)
-               return;
-
-       if (code->mcode != NULL)
-               CFREE((void *) (ptrint) code->mcode, code->mcodelength);
-
-       patcher_list_free(code);
-
-#if defined(ENABLE_JITCACHE)
-       jitcache_list_free(code);
-#endif
-
-#if defined(ENABLE_REPLACEMENT)
-       replace_free_replacement_points(code);
-#endif
-
-       FREE(code, codeinfo);
-
-#if defined(ENABLE_STATISTICS)
-       if (opt_stat)
-               size_codeinfo -= sizeof(codeinfo);
-#endif
-}
-
-
-/* code_free_code_of_method ****************************************************
-
-   Free all codeinfos of the given method
-   
-   IN:
-       m................the method of which the codeinfos are to be freed
-
-*******************************************************************************/
-
-void code_free_code_of_method(methodinfo *m)
-{
-       codeinfo *nextcode;
-       codeinfo *code;
-
-       if (!m)
-               return;
-       
-       nextcode = m->code;
-       while (nextcode) {
-               code = nextcode;
-               nextcode = code->prev;
-               code_codeinfo_free(code);
-       }
-
-       m->code = NULL;
-}
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
diff --git a/src/vm/jit/code.cpp b/src/vm/jit/code.cpp
new file mode 100644 (file)
index 0000000..a991de2
--- /dev/null
@@ -0,0 +1,299 @@
+/* src/vm/jit/code.cpp - codeinfo struct for representing compiled 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.
+
+*/
+
+
+#include "config.h"
+
+#include <assert.h>
+#include <stdint.h>
+
+#include "arch.h"
+
+#include "mm/memory.h"
+
+#include "vm/options.h"
+#include "vm/vm.hpp"
+
+#include "vm/jit/code.hpp"
+#include "vm/jit/codegen-common.hpp"
+#include "vm/jit/jitcache.hpp"
+#include "vm/jit/patcher-common.hpp"
+#include "vm/jit/methodtree.h"
+
+
+/* code_init *******************************************************************
+
+   Initialize the code-subsystem.
+
+*******************************************************************************/
+
+void code_init(void)
+{
+       /* Check if offset of codeinfo.m == 0 (see comment in code.h). */
+
+       if (OFFSET(codeinfo, m) != 0)
+               vm_abort("code_init: offset of codeinfo.m != 0: %d != 0", OFFSET(codeinfo, m));
+}
+
+
+/* code_codeinfo_new ***********************************************************
+
+   Create a new codeinfo for the given method.
+   
+   IN:
+       m................method to create a new codeinfo for
+
+   The following fields are set in codeinfo:
+       m
+       patchers
+          cachedrefs
+
+   RETURN VALUE:
+       a new, initialized codeinfo, or
+          NULL if an exception occurred.
+  
+*******************************************************************************/
+
+codeinfo *code_codeinfo_new(methodinfo *m)
+{
+       codeinfo *code;
+
+       code = NEW(codeinfo);
+
+       code->m = m;
+
+       patcher_list_create(code);
+
+#if defined (ENABLE_JITCACHE)
+       jitcache_list_create(code);
+#endif
+
+#if defined (ENABLE_STATISTICS)
+       if (opt_stat)
+               size_codeinfo += sizeof(codeinfo);
+#endif
+
+       return code;
+}
+
+
+/* code_find_codeinfo_for_pc ***************************************************
+
+   Return the codeinfo for the compilation unit that contains the
+   given PC.
+
+   ARGUMENTS:
+       pc...............machine code position
+
+   RETURN VALUE:
+       the codeinfo * for the given PC
+
+*******************************************************************************/
+
+codeinfo *code_find_codeinfo_for_pc(void *pc)
+{
+       void *pv;
+
+       pv = methodtree_find(pc);
+
+       return code_get_codeinfo_for_pv(pv);
+}
+
+
+/* code_find_codeinfo_for_pc ***************************************************
+
+   Return the codeinfo for the compilation unit that contains the
+   given PC. This method does not check the return value and is used
+   by the GC.
+
+   IN:
+       pc...............machine code position
+
+   RETURN VALUE:
+       the codeinfo * for the given PC, or NULL
+
+*******************************************************************************/
+
+codeinfo *code_find_codeinfo_for_pc_nocheck(void *pc)
+{
+       void *pv;
+
+       pv = methodtree_find_nocheck(pc);
+
+       if (pv == NULL)
+               return NULL;
+
+       return code_get_codeinfo_for_pv(pv);
+}
+
+
+/* code_get_methodinfo_for_pv **************************************************
+
+   Return the methodinfo for the given PV.
+
+   IN:
+       pv...............PV
+
+   RETURN VALUE:
+       the methodinfo *
+
+*******************************************************************************/
+
+methodinfo *code_get_methodinfo_for_pv(void *pv)
+{
+       codeinfo *code;
+
+       code = code_get_codeinfo_for_pv(pv);
+
+       /* This is the case for asm_vm_call_method. */
+
+       if (code == NULL)
+               return NULL;
+
+       return code->m;
+}
+
+
+/* code_get_sync_slot_count ****************************************************
+
+   Return the number of stack slots used for storing the synchronized object
+   (and the return value around lock_monitor_exit calls) by the given code.
+   
+   IN:
+       code.............the codeinfo of the code in question
+                           (must be != NULL)
+
+   RETURN VALUE:
+       the number of stack slots used for synchronization
+  
+*******************************************************************************/
+
+#if defined(ENABLE_REPLACEMENT)
+int code_get_sync_slot_count(codeinfo *code)
+{
+#ifdef ENABLE_THREADS
+       int count;
+       
+       assert(code);
+
+       if (!checksync)
+               return 0;
+
+       if (!code_is_synchronized(code))
+               return 0;
+
+       count = 1;
+
+#if defined(__POWERPC__)
+       /* powerpc needs an extra slot */
+       count++;
+#endif
+
+       return count;
+
+#else /* !ENABLE_THREADS */
+       
+       return 0;
+
+#endif /* ENABLE_THREADS */
+}
+#endif /* defined(ENABLE_REPLACEMENT) */
+
+
+/* code_codeinfo_free **********************************************************
+
+   Free the memory used by a codeinfo.
+   
+   IN:
+       code.............the codeinfo to free
+
+*******************************************************************************/
+
+void code_codeinfo_free(codeinfo *code)
+{
+       if (code == NULL)
+               return;
+
+       if (code->mcode != NULL)
+               CFREE((void *) (ptrint) code->mcode, code->mcodelength);
+
+       patcher_list_free(code);
+
+#if defined(ENABLE_JITCACHE)
+       jitcache_list_free(code);
+#endif
+
+#if defined(ENABLE_REPLACEMENT)
+       replace_free_replacement_points(code);
+#endif
+
+       FREE(code, codeinfo);
+
+#if defined(ENABLE_STATISTICS)
+       if (opt_stat)
+               size_codeinfo -= sizeof(codeinfo);
+#endif
+}
+
+
+/* code_free_code_of_method ****************************************************
+
+   Free all codeinfos of the given method
+   
+   IN:
+       m................the method of which the codeinfos are to be freed
+
+*******************************************************************************/
+
+void code_free_code_of_method(methodinfo *m)
+{
+       codeinfo *nextcode;
+       codeinfo *code;
+
+       if (!m)
+               return;
+       
+       nextcode = m->code;
+       while (nextcode) {
+               code = nextcode;
+               nextcode = code->prev;
+               code_codeinfo_free(code);
+       }
+
+       m->code = NULL;
+}
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
diff --git a/src/vm/jit/code.h b/src/vm/jit/code.h
deleted file mode 100644 (file)
index af2849a..0000000
+++ /dev/null
@@ -1,243 +0,0 @@
-/* src/vm/jit/code.h - codeinfo struct for representing compiled 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 _CODE_H
-#define _CODE_H
-
-#include "config.h"
-
-#include <assert.h>
-#include <stdint.h>
-
-#include "vm/types.h"
-
-#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"
-
-
-/* constants ******************************************************************/
-
-#define CODE_FLAG_INVALID         0x0001
-#define CODE_FLAG_LEAFMETHOD      0x0002
-#define CODE_FLAG_SYNCHRONIZED    0x0004
-#define CODE_FLAG_TLH             0x0008
-
-
-/* codeinfo *******************************************************************
-
-   A codeinfo represents a particular realization of a method in
-   machine code.
-
-   ATTENTION: The methodinfo entry in the code-structure MUST have the
-   offset 0, otherwise we have a problem in our compiler stub. This is
-   checked with an assert in code_init().
-
-*******************************************************************************/
-
-struct codeinfo {
-       methodinfo   *m;                    /* method this is a realization of    */
-       codeinfo     *prev;                 /* previous codeinfo of this method   */
-
-       uint32_t      flags;                /* OR of CODE_FLAG_ constants         */
-
-       u1            optlevel;             /* optimization level of this code    */
-       s4            basicblockcount;      /* number of basic blocks             */
-
-       int32_t       synchronizedoffset;   /* stack offset of synchronized obj.  */
-
-       /* machine code */
-       u1           *mcode;                /* pointer to machine code            */
-       u1           *entrypoint;           /* machine code entry point           */
-       s4            mcodelength;          /* length of generated machine code   */
-
-       exceptiontable_t  *exceptiontable;
-       linenumbertable_t *linenumbertable;
-
-       /* patcher list */
-       list_t       *patchers;
-
-#if defined (ENABLE_JITCACHE)
-       list_t           *cachedrefs;
-#endif
-
-       /* replacement */                                   
-       s4            stackframesize;       /* size of the stackframe in slots    */
-
-#if defined(ENABLE_REPLACEMENT)
-       rplpoint     *rplpoints;            /* replacement points                 */
-       rplalloc     *regalloc;             /* register allocation info           */
-       s4            rplpointcount;        /* number of replacement points       */
-       s4            globalcount;          /* number of global allocations       */
-       s4            regalloccount;        /* number of total allocations        */
-       s4            memuse;               /* number of arg + local slots        */
-       u1            savedintcount;        /* number of callee saved int regs    */
-       u1            savedfltcount;        /* number of callee saved flt regs    */
-# if defined(HAS_ADDRESS_REGISTER_FILE)
-       u1            savedadrcount;        /* number of callee saved adr regs    */
-# endif
-       u1           *savedmcode;           /* saved code under patches           */
-#endif
-
-#if defined(ENABLE_PROFILING)
-       u4            frequency;            /* number of method invocations       */
-       u4           *bbfrequency;                  
-       s8            cycles;               /* number of cpu cycles               */
-#endif
-};
-
-
-/* inline functions ***********************************************************/
-
-/* code_xxx_invalid ************************************************************
-
-   Functions for CODE_FLAG_INVALID.
-
-*******************************************************************************/
-
-inline static int code_is_invalid(codeinfo *code)
-{
-       return (code->flags & CODE_FLAG_INVALID);
-}
-
-inline static void code_flag_invalid(codeinfo *code)
-{
-       code->flags |= CODE_FLAG_INVALID;
-}
-
-inline static void code_unflag_invalid(codeinfo *code)
-{
-       code->flags &= ~CODE_FLAG_INVALID;
-}
-
-
-/* code_xxx_leafmethod *********************************************************
-
-   Functions for CODE_FLAG_LEAFMETHOD.
-
-*******************************************************************************/
-
-inline static int code_is_leafmethod(codeinfo *code)
-{
-       return (code->flags & CODE_FLAG_LEAFMETHOD);
-}
-
-inline static void code_flag_leafmethod(codeinfo *code)
-{
-       code->flags |= CODE_FLAG_LEAFMETHOD;
-}
-
-inline static void code_unflag_leafmethod(codeinfo *code)
-{
-       code->flags &= ~CODE_FLAG_LEAFMETHOD;
-}
-
-
-/* code_xxx_synchronized *******************************************************
-
-   Functions for CODE_FLAG_SYNCHRONIZED.
-
-*******************************************************************************/
-
-inline static int code_is_synchronized(codeinfo *code)
-{
-       return (code->flags & CODE_FLAG_SYNCHRONIZED);
-}
-
-inline static void code_flag_synchronized(codeinfo *code)
-{
-       code->flags |= CODE_FLAG_SYNCHRONIZED;
-}
-
-inline static void code_unflag_synchronized(codeinfo *code)
-{
-       code->flags &= ~CODE_FLAG_SYNCHRONIZED;
-}
-
-
-/* code_get_codeinfo_for_pv ****************************************************
-
-   Return the codeinfo for the given PV.
-
-   IN:
-       pv...............PV
-
-   RETURN VALUE:
-       the codeinfo *
-
-*******************************************************************************/
-
-inline static codeinfo *code_get_codeinfo_for_pv(void *pv)
-{
-       codeinfo *code;
-
-       assert(pv != NULL);
-
-       code = *((codeinfo **) (((uintptr_t) pv) + CodeinfoPointer));
-
-       return code;
-}
-
-
-/* function prototypes ********************************************************/
-
-void code_init(void);
-
-codeinfo *code_codeinfo_new(methodinfo *m);
-void code_codeinfo_free(codeinfo *code);
-
-codeinfo *code_find_codeinfo_for_pc(void *pc);
-codeinfo *code_find_codeinfo_for_pc_nocheck(void *pc);
-
-methodinfo *code_get_methodinfo_for_pv(void *pv);
-
-#if defined(ENABLE_REPLACEMENT)
-int code_get_sync_slot_count(codeinfo *code);
-#endif /* defined(ENABLE_REPLACEMENT) */
-
-void code_free_code_of_method(methodinfo *m);
-
-#endif /* _CODE_H */
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
diff --git a/src/vm/jit/code.hpp b/src/vm/jit/code.hpp
new file mode 100644 (file)
index 0000000..fcdb08c
--- /dev/null
@@ -0,0 +1,263 @@
+/* src/vm/jit/code.hpp - codeinfo struct for representing compiled 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 _CODE_HPP
+#define _CODE_HPP
+
+#include "config.h"
+
+#include <assert.h>
+#include <stdint.h>
+
+#include "vm/types.h"
+
+#include "toolbox/list.hpp"
+
+#include "vm/global.h"
+#include "vm/method.h"
+
+#include "vm/jit/exceptiontable.h"
+#if defined (ENABLE_JITCACHE)
+#include "vm/jit/jitcache.hpp"
+#endif
+#include "vm/jit/linenumbertable.hpp"
+#include "vm/jit/methodheader.h"
+#include "vm/jit/patcher-common.hpp"
+#include "vm/jit/replace.hpp"
+
+
+/* constants ******************************************************************/
+
+#define CODE_FLAG_INVALID         0x0001
+#define CODE_FLAG_LEAFMETHOD      0x0002
+#define CODE_FLAG_SYNCHRONIZED    0x0004
+#define CODE_FLAG_TLH             0x0008
+
+
+/* codeinfo *******************************************************************
+
+   A codeinfo represents a particular realization of a method in
+   machine code.
+
+   ATTENTION: The methodinfo entry in the code-structure MUST have the
+   offset 0, otherwise we have a problem in our compiler stub. This is
+   checked with an assert in code_init().
+
+*******************************************************************************/
+
+struct codeinfo {
+       methodinfo   *m;                    /* method this is a realization of    */
+       codeinfo     *prev;                 /* previous codeinfo of this method   */
+
+       uint32_t      flags;                /* OR of CODE_FLAG_ constants         */
+
+       u1            optlevel;             /* optimization level of this code    */
+       s4            basicblockcount;      /* number of basic blocks             */
+
+       int32_t       synchronizedoffset;   /* stack offset of synchronized obj.  */
+
+       /* machine code */
+       u1           *mcode;                /* pointer to machine code            */
+       u1           *entrypoint;           /* machine code entry point           */
+       s4            mcodelength;          /* length of generated machine code   */
+
+       exceptiontable_t  *exceptiontable;
+       LinenumberTable* linenumbertable;
+
+       /* patcher list */
+#ifdef __cplusplus
+       List<patchref_t>* patchers;
+#else
+       List*         patchers;
+#endif
+
+#if defined (ENABLE_JITCACHE)
+#ifdef __cplusplus
+       List<cachedref_t>* cachedrefs;
+#else
+       List*         cachedrefs;
+#endif
+#endif
+
+       /* replacement */                                   
+       s4            stackframesize;       /* size of the stackframe in slots    */
+
+#if defined(ENABLE_REPLACEMENT)
+       rplpoint     *rplpoints;            /* replacement points                 */
+       rplalloc     *regalloc;             /* register allocation info           */
+       s4            rplpointcount;        /* number of replacement points       */
+       s4            globalcount;          /* number of global allocations       */
+       s4            regalloccount;        /* number of total allocations        */
+       s4            memuse;               /* number of arg + local slots        */
+       u1            savedintcount;        /* number of callee saved int regs    */
+       u1            savedfltcount;        /* number of callee saved flt regs    */
+# if defined(HAS_ADDRESS_REGISTER_FILE)
+       u1            savedadrcount;        /* number of callee saved adr regs    */
+# endif
+       u1           *savedmcode;           /* saved code under patches           */
+#endif
+
+#if defined(ENABLE_PROFILING)
+       u4            frequency;            /* number of method invocations       */
+       u4           *bbfrequency;                  
+       s8            cycles;               /* number of cpu cycles               */
+#endif
+};
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* inline functions ***********************************************************/
+
+/* code_xxx_invalid ************************************************************
+
+   Functions for CODE_FLAG_INVALID.
+
+*******************************************************************************/
+
+inline static int code_is_invalid(codeinfo *code)
+{
+       return (code->flags & CODE_FLAG_INVALID);
+}
+
+inline static void code_flag_invalid(codeinfo *code)
+{
+       code->flags |= CODE_FLAG_INVALID;
+}
+
+inline static void code_unflag_invalid(codeinfo *code)
+{
+       code->flags &= ~CODE_FLAG_INVALID;
+}
+
+
+/* code_xxx_leafmethod *********************************************************
+
+   Functions for CODE_FLAG_LEAFMETHOD.
+
+*******************************************************************************/
+
+inline static int code_is_leafmethod(codeinfo *code)
+{
+       return (code->flags & CODE_FLAG_LEAFMETHOD);
+}
+
+inline static void code_flag_leafmethod(codeinfo *code)
+{
+       code->flags |= CODE_FLAG_LEAFMETHOD;
+}
+
+inline static void code_unflag_leafmethod(codeinfo *code)
+{
+       code->flags &= ~CODE_FLAG_LEAFMETHOD;
+}
+
+
+/* code_xxx_synchronized *******************************************************
+
+   Functions for CODE_FLAG_SYNCHRONIZED.
+
+*******************************************************************************/
+
+inline static int code_is_synchronized(codeinfo *code)
+{
+       return (code->flags & CODE_FLAG_SYNCHRONIZED);
+}
+
+inline static void code_flag_synchronized(codeinfo *code)
+{
+       code->flags |= CODE_FLAG_SYNCHRONIZED;
+}
+
+inline static void code_unflag_synchronized(codeinfo *code)
+{
+       code->flags &= ~CODE_FLAG_SYNCHRONIZED;
+}
+
+
+/* code_get_codeinfo_for_pv ****************************************************
+
+   Return the codeinfo for the given PV.
+
+   IN:
+       pv...............PV
+
+   RETURN VALUE:
+       the codeinfo *
+
+*******************************************************************************/
+
+inline static codeinfo *code_get_codeinfo_for_pv(void *pv)
+{
+       codeinfo *code;
+
+       assert(pv != NULL);
+
+       code = *((codeinfo **) (((uintptr_t) pv) + CodeinfoPointer));
+
+       return code;
+}
+
+
+/* function prototypes ********************************************************/
+
+void code_init(void);
+
+codeinfo *code_codeinfo_new(methodinfo *m);
+void code_codeinfo_free(codeinfo *code);
+
+codeinfo *code_find_codeinfo_for_pc(void *pc);
+codeinfo *code_find_codeinfo_for_pc_nocheck(void *pc);
+
+methodinfo *code_get_methodinfo_for_pv(void *pv);
+
+#if defined(ENABLE_REPLACEMENT)
+int code_get_sync_slot_count(codeinfo *code);
+#endif /* defined(ENABLE_REPLACEMENT) */
+
+void code_free_code_of_method(methodinfo *m);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _CODE_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:
+ */
diff --git a/src/vm/jit/codegen-common.c b/src/vm/jit/codegen-common.c
deleted file mode 100644 (file)
index 4d4733d..0000000
+++ /dev/null
@@ -1,1484 +0,0 @@
-/* src/vm/jit/codegen-common.c - architecture independent code generator stuff
-
-   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.
-
-   All functions assume the following code area / data area layout:
-
-   +-----------+
-   |           |
-   | code area | code area grows to higher addresses
-   |           |
-   +-----------+ <-- start of procedure
-   |           |
-   | data area | data area grows to lower addresses
-   |           |
-   +-----------+
-
-   The functions first write into a temporary code/data area allocated by
-   "codegen_init". "codegen_finish" copies the code and data area into permanent
-   memory. All functions writing values into the data area return the offset
-   relative the begin of the code area (start of procedure).   
-
-*/
-
-
-#include "config.h"
-
-#include <assert.h>
-#include <string.h>
-
-#include "vm/jit/jitcache.hpp"
-
-#include "vm/types.h"
-
-#include "codegen.h"
-#include "md.h"
-#include "md-abi.h"
-
-#include "mm/memory.h"
-
-#include "toolbox/avl.h"
-#include "toolbox/list.h"
-#include "toolbox/logging.h"
-
-#include "native/jni.h"
-#include "native/llni.h"
-#include "native/localref.h"
-#include "native/native.h"
-
-#include "threads/thread.hpp"
-
-#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/codegen-common.h"
-
-#if defined(ENABLE_DISASSEMBLER)
-# include "vm/jit/disass.h"
-#endif
-
-#include "vm/jit/dseg.h"
-#include "vm/jit/emit-common.h"
-#include "vm/jit/jit.h"
-#include "vm/jit/linenumbertable.h"
-#include "vm/jit/methodheader.h"
-#include "vm/jit/methodtree.h"
-#include "vm/jit/patcher-common.h"
-#include "vm/jit/replace.h"
-#if defined(ENABLE_SSA)
-# include "vm/jit/optimizing/lsra.h"
-# include "vm/jit/optimizing/ssa.h"
-#endif
-#include "vm/jit/stacktrace.hpp"
-#include "vm/jit/trace.hpp"
-
-#if defined(ENABLE_INTRP)
-#include "vm/jit/intrp/intrp.h"
-#endif
-
-#if defined(ENABLE_VMLOG)
-#include <vmlog_cacao.h>
-#endif
-
-#include "show.h"
-
-
-/* codegen_init ****************************************************************
-
-   TODO
-
-*******************************************************************************/
-
-void codegen_init(void)
-{
-}
-
-
-/* codegen_setup ***************************************************************
-
-   Allocates and initialises code area, data area and references.
-
-*******************************************************************************/
-
-void codegen_setup(jitdata *jd)
-{
-       methodinfo  *m;
-       codegendata *cd;
-
-       /* get required compiler data */
-
-       m  = jd->m;
-       cd = jd->cd;
-
-       /* initialize members */
-
-       cd->flags        = 0;
-
-       cd->mcodebase    = DMNEW(u1, MCODEINITSIZE);
-       cd->mcodeend     = cd->mcodebase + MCODEINITSIZE;
-       cd->mcodesize    = MCODEINITSIZE;
-
-       /* initialize mcode variables */
-
-       cd->mcodeptr     = cd->mcodebase;
-       cd->lastmcodeptr = cd->mcodebase;
-
-#if defined(ENABLE_INTRP)
-       /* native dynamic superinstructions variables */
-
-       if (opt_intrp) {
-               cd->ncodebase = DMNEW(u1, NCODEINITSIZE);
-               cd->ncodesize = NCODEINITSIZE;
-
-               /* initialize ncode variables */
-       
-               cd->ncodeptr = cd->ncodebase;
-
-               cd->lastinstwithoutdispatch = ~0; /* no inst without dispatch */
-               cd->superstarts = NULL;
-       }
-#endif
-
-       cd->dseg           = NULL;
-       cd->dseglen        = 0;
-
-       cd->jumpreferences = NULL;
-
-#if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
-       cd->datareferences = NULL;
-#endif
-
-       cd->brancheslabel  = list_create_dump(OFFSET(branch_label_ref_t, linkage));
-       cd->linenumbers    = list_create_dump(OFFSET(linenumbertable_list_entry_t, linkage));
-}
-
-
-/* codegen_reset ***************************************************************
-
-   Resets the codegen data structure so we can recompile the method.
-
-*******************************************************************************/
-
-static void codegen_reset(jitdata *jd)
-{
-       codeinfo    *code;
-       codegendata *cd;
-       basicblock  *bptr;
-
-       /* get required compiler data */
-
-       code = jd->code;
-       cd   = jd->cd;
-
-       /* reset error flag */
-
-       cd->flags          &= ~CODEGENDATA_FLAG_ERROR;
-
-       /* reset some members, we reuse the code memory already allocated
-          as this should have almost the correct size */
-
-       cd->mcodeptr        = cd->mcodebase;
-       cd->lastmcodeptr    = cd->mcodebase;
-
-       cd->dseg            = NULL;
-       cd->dseglen         = 0;
-
-       cd->jumpreferences  = NULL;
-
-#if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
-       cd->datareferences  = NULL;
-#endif
-
-       cd->brancheslabel   = list_create_dump(OFFSET(branch_label_ref_t, linkage));
-       cd->linenumbers     = list_create_dump(OFFSET(linenumbertable_list_entry_t, linkage));
-       
-       /* We need to clear the mpc and the branch references from all
-          basic blocks as they will definitely change. */
-
-       for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
-               bptr->mpc        = -1;
-               bptr->branchrefs = NULL;
-       }
-
-       /* We need to clear all the patcher references from the codeinfo
-          since they all will be regenerated */
-
-       patcher_list_reset(code);
-
-#if defined(ENABLE_REPLACEMENT)
-       code->rplpoints     = NULL;
-       code->rplpointcount = 0;
-       code->regalloc      = NULL;
-       code->regalloccount = 0;
-       code->globalcount   = 0;
-#endif
-}
-
-
-/* codegen_generate ************************************************************
-
-   Generates the code for the currently compiled method.
-
-*******************************************************************************/
-
-bool codegen_generate(jitdata *jd)
-{
-       codegendata *cd;
-
-       /* get required compiler data */
-
-       cd = jd->cd;
-
-       /* call the machine-dependent code generation function */
-
-       if (!codegen_emit(jd))
-               return false;
-
-       /* check for an error */
-
-       if (CODEGENDATA_HAS_FLAG_ERROR(cd)) {
-               /* check for long-branches flag, if it is set we recompile the
-                  method */
-
-#if !defined(NDEBUG)
-        if (compileverbose)
-            log_message_method("Re-generating code: ", jd->m);
-#endif
-
-               /* XXX maybe we should tag long-branches-methods for recompilation */
-
-               if (CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
-                       /* we have to reset the codegendata structure first */
-
-                       codegen_reset(jd);
-
-                       /* and restart the compiler run */
-
-                       if (!codegen_emit(jd))
-                               return false;
-               }
-               else {
-                       vm_abort("codegen_generate: unknown error occurred during codegen_emit: flags=%x\n", cd->flags);
-               }
-
-#if !defined(NDEBUG)
-        if (compileverbose)
-            log_message_method("Re-generating code done: ", jd->m);
-#endif
-       }
-
-       /* reallocate the memory and finish the code generation */
-
-       codegen_finish(jd);
-
-       /* everything's ok */
-
-       return true;
-}
-
-
-/* codegen_close ***************************************************************
-
-   TODO
-
-*******************************************************************************/
-
-void codegen_close(void)
-{
-       /* TODO: release avl tree on i386 and x86_64 */
-}
-
-
-/* codegen_increase ************************************************************
-
-   Doubles code area.
-
-*******************************************************************************/
-
-void codegen_increase(codegendata *cd)
-{
-       u1 *oldmcodebase;
-
-       /* save old mcodebase pointer */
-
-       oldmcodebase = cd->mcodebase;
-
-       /* reallocate to new, doubled memory */
-
-       cd->mcodebase = DMREALLOC(cd->mcodebase,
-                                                         u1,
-                                                         cd->mcodesize,
-                                                         cd->mcodesize * 2);
-       cd->mcodesize *= 2;
-       cd->mcodeend   = cd->mcodebase + cd->mcodesize;
-
-       /* set new mcodeptr */
-
-       cd->mcodeptr = cd->mcodebase + (cd->mcodeptr - oldmcodebase);
-
-#if defined(__I386__) || defined(__MIPS__) || defined(__X86_64__) || defined(__M68K__) || defined(ENABLE_INTRP) \
- || defined(__SPARC_64__)
-       /* adjust the pointer to the last patcher position */
-
-       if (cd->lastmcodeptr != NULL)
-               cd->lastmcodeptr = cd->mcodebase + (cd->lastmcodeptr - oldmcodebase);
-#endif
-}
-
-
-/* codegen_ncode_increase ******************************************************
-
-   Doubles code area.
-
-*******************************************************************************/
-
-#if defined(ENABLE_INTRP)
-u1 *codegen_ncode_increase(codegendata *cd, u1 *ncodeptr)
-{
-       u1 *oldncodebase;
-
-       /* save old ncodebase pointer */
-
-       oldncodebase = cd->ncodebase;
-
-       /* reallocate to new, doubled memory */
-
-       cd->ncodebase = DMREALLOC(cd->ncodebase,
-                                                         u1,
-                                                         cd->ncodesize,
-                                                         cd->ncodesize * 2);
-       cd->ncodesize *= 2;
-
-       /* return the new ncodeptr */
-
-       return (cd->ncodebase + (ncodeptr - oldncodebase));
-}
-#endif
-
-
-/* codegen_add_branch_ref ******************************************************
-
-   Prepends an branch to the list.
-
-*******************************************************************************/
-
-void codegen_add_branch_ref(codegendata *cd, basicblock *target, s4 condition, s4 reg, u4 options)
-{
-       branchref *br;
-       s4         branchmpc;
-
-       STATISTICS(count_branches_unresolved++);
-
-       /* calculate the mpc of the branch instruction */
-
-       branchmpc = cd->mcodeptr - cd->mcodebase;
-
-       br = DNEW(branchref);
-
-       br->branchmpc = branchmpc;
-       br->condition = condition;
-       br->reg       = reg;
-       br->options   = options;
-       br->next      = target->branchrefs;
-
-       target->branchrefs = br;
-}
-
-
-/* codegen_resolve_branchrefs **************************************************
-
-   Resolves and patches the branch references of a given basic block.
-
-*******************************************************************************/
-
-void codegen_resolve_branchrefs(codegendata *cd, basicblock *bptr)
-{
-       branchref *br;
-       u1        *mcodeptr;
-
-       /* Save the mcodeptr because in the branch emitting functions
-          we generate code somewhere inside already generated code,
-          but we're still in the actual code generation phase. */
-
-       mcodeptr = cd->mcodeptr;
-
-       /* just to make sure */
-
-       assert(bptr->mpc >= 0);
-
-       for (br = bptr->branchrefs; br != NULL; br = br->next) {
-               /* temporary set the mcodeptr */
-
-               cd->mcodeptr = cd->mcodebase + br->branchmpc;
-
-               /* emit_bccz and emit_branch emit the correct code, even if we
-                  pass condition == BRANCH_UNCONDITIONAL or reg == -1. */
-
-               emit_bccz(cd, bptr, br->condition, br->reg, br->options);
-       }
-
-       /* restore mcodeptr */
-
-       cd->mcodeptr = mcodeptr;
-}
-
-
-/* codegen_branch_label_add ****************************************************
-
-   Append an branch to the label-branch list.
-
-*******************************************************************************/
-
-void codegen_branch_label_add(codegendata *cd, s4 label, s4 condition, s4 reg, u4 options)
-{
-       list_t             *l;
-       branch_label_ref_t *br;
-       s4                  mpc;
-
-       /* Get the label list. */
-
-       l = cd->brancheslabel;
-       
-       /* calculate the current mpc */
-
-       mpc = cd->mcodeptr - cd->mcodebase;
-
-       br = DNEW(branch_label_ref_t);
-
-       br->mpc       = mpc;
-       br->label     = label;
-       br->condition = condition;
-       br->reg       = reg;
-       br->options   = options;
-
-       /* Add the branch to the list. */
-
-       list_add_last(l, br);
-}
-
-
-/* codegen_set_replacement_point_notrap ****************************************
-
-   Record the position of a non-trappable replacement point.
-
-*******************************************************************************/
-
-#if defined(ENABLE_REPLACEMENT)
-#if !defined(NDEBUG)
-void codegen_set_replacement_point_notrap(codegendata *cd, s4 type)
-#else
-void codegen_set_replacement_point_notrap(codegendata *cd)
-#endif
-{
-       assert(cd->replacementpoint);
-       assert(cd->replacementpoint->type == type);
-       assert(cd->replacementpoint->flags & RPLPOINT_FLAG_NOTRAP);
-
-       cd->replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
-
-       cd->replacementpoint++;
-}
-#endif /* defined(ENABLE_REPLACEMENT) */
-
-
-/* codegen_set_replacement_point ***********************************************
-
-   Record the position of a trappable replacement point.
-
-*******************************************************************************/
-
-#if defined(ENABLE_REPLACEMENT)
-#if !defined(NDEBUG)
-void codegen_set_replacement_point(codegendata *cd, s4 type)
-#else
-void codegen_set_replacement_point(codegendata *cd)
-#endif
-{
-       assert(cd->replacementpoint);
-       assert(cd->replacementpoint->type == type);
-       assert(!(cd->replacementpoint->flags & RPLPOINT_FLAG_NOTRAP));
-
-       cd->replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
-
-       cd->replacementpoint++;
-
-#if !defined(NDEBUG)
-       /* XXX actually we should use an own REPLACEMENT_NOPS here! */
-       if (opt_TestReplacement)
-               PATCHER_NOPS;
-#endif
-
-       /* XXX assert(cd->lastmcodeptr <= cd->mcodeptr); */
-
-       cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
-}
-#endif /* defined(ENABLE_REPLACEMENT) */
-
-
-/* codegen_finish **************************************************************
-
-   Finishes the code generation. A new memory, large enough for both
-   data and code, is allocated and data and code are copied together
-   to their final layout, unresolved jumps are resolved, ...
-
-*******************************************************************************/
-
-void codegen_finish(jitdata *jd)
-{
-       codeinfo    *code;
-       codegendata *cd;
-       s4           mcodelen;
-#if defined(ENABLE_INTRP)
-       s4           ncodelen;
-#endif
-       s4           alignedmcodelen;
-       jumpref     *jr;
-       u1          *epoint;
-       s4           alignedlen;
-
-       /* get required compiler data */
-
-       code = jd->code;
-       cd   = jd->cd;
-
-       /* prevent compiler warning */
-
-#if defined(ENABLE_INTRP)
-       ncodelen = 0;
-#endif
-
-       /* calculate the code length */
-
-       mcodelen = (s4) (cd->mcodeptr - cd->mcodebase);
-
-#if defined(ENABLE_STATISTICS)
-       if (opt_stat) {
-               count_code_len += mcodelen;
-               count_data_len += cd->dseglen;
-       }
-#endif
-
-       alignedmcodelen = MEMORY_ALIGN(mcodelen, MAX_ALIGN);
-
-#if defined(ENABLE_INTRP)
-       if (opt_intrp)
-               ncodelen = cd->ncodeptr - cd->ncodebase;
-       else {
-               ncodelen = 0; /* avoid compiler warning */
-       }
-#endif
-
-       cd->dseglen = MEMORY_ALIGN(cd->dseglen, MAX_ALIGN);
-       alignedlen = alignedmcodelen + cd->dseglen;
-
-#if defined(ENABLE_INTRP)
-       if (opt_intrp) {
-               alignedlen += ncodelen;
-       }
-#endif
-
-       /* allocate new memory */
-
-       code->mcodelength = mcodelen + cd->dseglen;
-       code->mcode       = CNEW(u1, alignedlen);
-
-       /* set the entrypoint of the method */
-       
-       assert(code->entrypoint == NULL);
-       code->entrypoint = epoint = (code->mcode + cd->dseglen);
-
-       /* fill the data segment (code->entrypoint must already be set!) */
-
-       dseg_finish(jd);
-
-       /* copy code to the new location */
-
-       MCOPY((void *) code->entrypoint, cd->mcodebase, u1, mcodelen);
-
-#if defined(ENABLE_INTRP)
-       /* relocate native dynamic superinstruction code (if any) */
-
-       if (opt_intrp) {
-               cd->mcodebase = code->entrypoint;
-
-               if (ncodelen > 0) {
-                       u1 *ncodebase = code->mcode + cd->dseglen + alignedmcodelen;
-
-                       MCOPY((void *) ncodebase, cd->ncodebase, u1, ncodelen);
-
-                       /* flush the instruction and data caches */
-
-                       md_cacheflush(ncodebase, ncodelen);
-
-                       /* set some cd variables for dynamic_super_rerwite */
-
-                       cd->ncodebase = ncodebase;
-
-               } else {
-                       cd->ncodebase = NULL;
-               }
-
-               dynamic_super_rewrite(cd);
-       }
-#endif
-
-       /* Create the exception table. */
-
-       exceptiontable_create(jd);
-
-       /* Create the linenumber table. */
-
-       linenumbertable_create(jd);
-
-       /* jump table resolving */
-
-       for (jr = cd->jumpreferences; jr != NULL; jr = jr->next)
-       {
-               *((functionptr *) ((ptrint) epoint + jr->tablepos)) =
-                       (functionptr) ((ptrint) epoint + (ptrint) jr->target->mpc);
-
-               JITCACHE_ADD_CACHED_REF(code, CRT_JUMPREFERENCE, jr->target->mpc, jr->tablepos);
-       }
-
-       /* patcher resolving */
-
-       patcher_resolve(jd);
-
-#if defined(ENABLE_REPLACEMENT)
-       /* replacement point resolving */
-       {
-               int i;
-               rplpoint *rp;
-
-               rp = code->rplpoints;
-               for (i=0; i<code->rplpointcount; ++i, ++rp) {
-                       rp->pc = (u1*) ((ptrint) epoint + (ptrint) rp->pc);
-               }
-       }
-#endif /* defined(ENABLE_REPLACEMENT) */
-
-       /* Insert method into methodtree to find the entrypoint. */
-
-       methodtree_insert(code->entrypoint, code->entrypoint + mcodelen);
-
-#if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
-       /* resolve data segment references */
-
-       dseg_resolve_datareferences(jd);
-#endif
-
-       /* flush the instruction and data caches */
-
-       md_cacheflush(code->mcode, code->mcodelength);
-}
-
-
-/* codegen_generate_stub_compiler **********************************************
-
-   Wrapper for codegen_emit_stub_compiler.
-
-   Returns:
-       pointer to the compiler stub code.
-
-*******************************************************************************/
-
-u1 *codegen_generate_stub_compiler(methodinfo *m)
-{
-       jitdata     *jd;
-       codegendata *cd;
-       ptrint      *d;                     /* pointer to data memory             */
-       u1          *c;                     /* pointer to code memory             */
-       int32_t      dumpmarker;
-
-       /* mark dump memory */
-
-       DMARKER;
-
-       /* allocate required data structures */
-
-       jd = DNEW(jitdata);
-
-       jd->m     = m;
-       jd->cd    = DNEW(codegendata);
-       jd->flags = 0;
-
-       /* get required compiler data */
-
-       cd = jd->cd;
-
-#if !defined(JIT_COMPILER_VIA_SIGNAL)
-       /* allocate code memory */
-
-       c = CNEW(u1, 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
-
-       /* set pointers correctly */
-
-       d = (ptrint *) c;
-
-       cd->mcodebase = c;
-
-       c = c + 3 * SIZEOF_VOID_P;
-       cd->mcodeptr = c;
-
-       /* NOTE: The codeinfo pointer is actually a pointer to the
-          methodinfo (this fakes a codeinfo structure). */
-
-       d[0] = (ptrint) asm_call_jit_compiler;
-       d[1] = (ptrint) m;
-       d[2] = (ptrint) &d[1];                                    /* fake code->m */
-
-       /* call the emit function */
-
-       codegen_emit_stub_compiler(jd);
-
-#if defined(ENABLE_STATISTICS)
-       if (opt_stat)
-               count_cstub_len += 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE;
-#endif
-
-       /* flush caches */
-
-       md_cacheflush(cd->mcodebase, 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
-#else
-       /* Allocate code memory. */
-
-       c = CNEW(uint8_t, 2 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
-
-       /* Set pointers correctly. */
-
-       d = (ptrint *) c;
-
-       cd->mcodebase = c;
-
-       c = c + 2 * SIZEOF_VOID_P;
-       cd->mcodeptr = c;
-
-       /* NOTE: The codeinfo pointer is actually a pointer to the
-          methodinfo (this fakes a codeinfo structure). */
-
-       d[0] = (ptrint) m;
-       d[1] = (ptrint) &d[0];                                    /* fake code->m */
-
-       /* Emit the trap instruction. */
-
-       emit_trap_compiler(cd);
-
-#if defined(ENABLE_STATISTICS)
-       if (opt_stat)
-               count_cstub_len += 2 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE;
-#endif
-
-       /* Flush caches. */
-
-       md_cacheflush(cd->mcodebase, 2 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
-#endif
-
-       /* release dump memory */
-
-       DRELEASE;
-
-       /* return native stub code */
-
-       return c;
-}
-
-
-/* codegen_generate_stub_builtin ***********************************************
-
-   Wrapper for codegen_emit_stub_native.
-
-*******************************************************************************/
-
-void codegen_generate_stub_builtin(methodinfo *m, builtintable_entry *bte)
-{
-       jitdata  *jd;
-       codeinfo *code;
-       int       skipparams;
-       int32_t   dumpmarker;
-
-       /* mark dump memory */
-
-       DMARKER;
-
-       /* Create JIT data structure. */
-
-       jd = jit_jitdata_new(m);
-
-       /* Get required compiler data. */
-
-       code = jd->code;
-
-       /* Stubs are non-leaf methods. */
-
-       code_unflag_leafmethod(code);
-
-       /* setup code generation stuff */
-
-       codegen_setup(jd);
-
-       /* Set the number of native arguments we need to skip. */
-
-       skipparams = 0;
-
-       /* generate the code */
-
-#if defined(ENABLE_JIT)
-# if defined(ENABLE_INTRP)
-       if (!opt_intrp) {
-# endif
-               assert(bte->fp != NULL);
-               codegen_emit_stub_native(jd, bte->md, bte->fp, skipparams);
-# if defined(ENABLE_INTRP)
-       }
-# endif
-#endif
-
-       /* reallocate the memory and finish the code generation */
-
-       codegen_finish(jd);
-
-       /* set the stub entry point in the builtin table */
-
-       bte->stub = code->entrypoint;
-
-#if defined(ENABLE_STATISTICS)
-       if (opt_stat)
-               size_stub_native += code->mcodelength;
-#endif
-
-#if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER)
-       /* disassemble native stub */
-
-       if (opt_DisassembleStubs) {
-               codegen_disassemble_stub(m,
-                                                                (u1 *) (ptrint) code->entrypoint,
-                                                                (u1 *) (ptrint) code->entrypoint + (code->mcodelength - jd->cd->dseglen));
-
-               /* show data segment */
-
-               if (opt_showddatasegment)
-                       dseg_display(jd);
-       }
-#endif /* !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER) */
-
-       /* release memory */
-
-       DRELEASE;
-}
-
-
-/* codegen_generate_stub_native ************************************************
-
-   Wrapper for codegen_emit_stub_native.
-
-   Returns:
-       the codeinfo representing the stub code.
-
-*******************************************************************************/
-
-codeinfo *codegen_generate_stub_native(methodinfo *m, functionptr f)
-{
-       jitdata     *jd;
-       codeinfo    *code;
-       methoddesc  *md;
-       methoddesc  *nmd;       
-       int          skipparams;
-       int32_t      dumpmarker;
-
-       /* mark dump memory */
-
-       DMARKER;
-
-       /* Create JIT data structure. */
-
-       jd = jit_jitdata_new(m);
-
-       /* Get required compiler data. */
-
-       code = jd->code;
-
-       /* Stubs are non-leaf methods. */
-
-       code_unflag_leafmethod(code);
-
-       /* set the flags for the current JIT run */
-
-#if defined(ENABLE_PROFILING)
-       if (opt_prof)
-               jd->flags |= JITDATA_FLAG_INSTRUMENT;
-#endif
-
-       if (opt_verbosecall)
-               jd->flags |= JITDATA_FLAG_VERBOSECALL;
-
-       /* setup code generation stuff */
-
-#if defined(ENABLE_JIT)
-# if defined(ENABLE_INTRP)
-       if (!opt_intrp)
-# endif
-               reg_setup(jd);
-#endif
-
-       codegen_setup(jd);
-
-       /* create new method descriptor with additional native parameters */
-
-       md = m->parseddesc;
-
-       /* Set the number of native arguments we need to skip. */
-
-       if (m->flags & ACC_STATIC)
-               skipparams = 2;
-       else
-               skipparams = 1;
-       
-       nmd = (methoddesc *) DMNEW(u1, sizeof(methoddesc) - sizeof(typedesc) +
-                                                          md->paramcount * sizeof(typedesc) +
-                                                          skipparams * sizeof(typedesc));
-
-       nmd->paramcount = md->paramcount + skipparams;
-
-       nmd->params = DMNEW(paramdesc, nmd->paramcount);
-
-       nmd->paramtypes[0].type = TYPE_ADR; /* add environment pointer            */
-
-       if (m->flags & ACC_STATIC)
-               nmd->paramtypes[1].type = TYPE_ADR; /* add class pointer              */
-
-       MCOPY(nmd->paramtypes + skipparams, md->paramtypes, typedesc,
-                 md->paramcount);
-
-#if defined(ENABLE_JIT)
-# if defined(ENABLE_INTRP)
-       if (!opt_intrp)
-# endif
-               /* pre-allocate the arguments for the native ABI */
-
-               md_param_alloc_native(nmd);
-#endif
-
-       /* generate the code */
-
-#if defined(ENABLE_JIT)
-# if defined(ENABLE_INTRP)
-       if (opt_intrp)
-               intrp_createnativestub(f, jd, nmd);
-       else
-# endif
-               codegen_emit_stub_native(jd, nmd, f, skipparams);
-#else
-       intrp_createnativestub(f, jd, nmd);
-#endif
-
-       /* reallocate the memory and finish the code generation */
-
-       codegen_finish(jd);
-
-#if defined(ENABLE_STATISTICS)
-       /* must be done after codegen_finish() */
-
-       if (opt_stat)
-               size_stub_native += code->mcodelength;
-#endif
-
-#if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER)
-       /* disassemble native stub */
-
-       if (opt_DisassembleStubs) {
-# if defined(ENABLE_DEBUG_FILTER)
-               if (m->filtermatches & SHOW_FILTER_FLAG_SHOW_METHOD)
-# endif
-               {
-                       codegen_disassemble_stub(m,
-                                                                        (u1 *) (ptrint) code->entrypoint,
-                                                                        (u1 *) (ptrint) code->entrypoint + (code->mcodelength - jd->cd->dseglen));
-
-                       /* show data segment */
-
-                       if (opt_showddatasegment)
-                               dseg_display(jd);
-               }
-       }
-#endif /* !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER) */
-
-       /* release memory */
-
-       DRELEASE;
-
-       /* return native stub code */
-
-       return code;
-}
-
-
-/* codegen_disassemble_nativestub **********************************************
-
-   Disassembles the generated builtin or native stub.
-
-*******************************************************************************/
-
-#if defined(ENABLE_DISASSEMBLER)
-void codegen_disassemble_stub(methodinfo *m, u1 *start, u1 *end)
-{
-       printf("Stub code: ");
-       if (m->clazz != NULL)
-               utf_fprint_printable_ascii_classname(stdout, m->clazz->name);
-       else
-               printf("NULL");
-       printf(".");
-       utf_fprint_printable_ascii(stdout, m->name);
-       utf_fprint_printable_ascii(stdout, m->descriptor);
-       printf("\nLength: %d\n\n", (s4) (end - start));
-
-       DISASSEMBLE(start, end);
-}
-#endif
-
-
-/* codegen_start_native_call ***************************************************
-
-   Prepares the stuff required for a native (JNI) function call:
-
-   - adds a stackframe info structure to the chain, for stacktraces
-   - prepares the local references table on the stack
-
-   The layout of the native stub stackframe should look like this:
-
-   +---------------------------+ <- java SP (of parent Java function)
-   | return address            |
-   +---------------------------+ <- data SP
-   |                           |
-   | stackframe info structure |
-   |                           |
-   +---------------------------+
-   |                           |
-   | local references table    |
-   |                           |
-   +---------------------------+
-   |                           |
-   | saved registers (if any)  |
-   |                           |
-   +---------------------------+
-   |                           |
-   | arguments (if any)        |
-   |                           |
-   +---------------------------+ <- current SP (native stub)
-
-*******************************************************************************/
-
-java_handle_t *codegen_start_native_call(u1 *sp, u1 *pv)
-{
-       stackframeinfo_t *sfi;
-       localref_table   *lrt;
-       methodinfo       *m;
-       int32_t           framesize;
-
-       uint8_t  *datasp;
-       uint8_t  *javasp;
-       uint64_t *arg_regs;
-       uint64_t *arg_stack;
-
-       STATISTICS(count_calls_java_to_native++);
-
-       /* Get the methodinfo. */
-
-       m = code_get_methodinfo_for_pv(pv);
-
-       assert(m);
-
-       framesize = *((int32_t *) (pv + FrameSize));
-
-       assert(framesize >= sizeof(stackframeinfo_t) + sizeof(localref_table));
-
-       /* calculate needed values */
-
-#if defined(__ALPHA__) || defined(__ARM__)
-       datasp    = sp + framesize - SIZEOF_VOID_P;
-       javasp    = sp + framesize;
-       arg_regs  = (uint64_t *) sp;
-       arg_stack = (uint64_t *) javasp;
-#elif defined(__MIPS__)
-       /* MIPS always uses 8 bytes to store the RA */
-       datasp    = sp + framesize - 8;
-       javasp    = sp + framesize;
-#elif defined(__S390__)
-       datasp    = sp + framesize - 8;
-       javasp    = sp + framesize;
-       arg_regs  = (uint64_t *) (sp + 96);
-       arg_stack = (uint64_t *) javasp;
-#elif defined(__I386__) || defined(__M68K__) || defined(__X86_64__)
-       datasp    = sp + framesize;
-       javasp    = sp + framesize + SIZEOF_VOID_P;
-       arg_regs  = (uint64_t *) sp;
-       arg_stack = (uint64_t *) javasp;
-#elif defined(__POWERPC__)
-       datasp    = sp + framesize;
-       javasp    = sp + framesize;
-       arg_regs  = (uint64_t *) (sp + LA_SIZE + 4 * SIZEOF_VOID_P);
-       arg_stack = (uint64_t *) javasp;
-#elif defined(__POWERPC64__)
-       datasp    = sp + framesize;
-       javasp    = sp + framesize;
-       arg_regs  = (uint64_t *) (sp + PA_SIZE + LA_SIZE + 4 * SIZEOF_VOID_P);
-       arg_stack = (uint64_t *) javasp;
-#else
-       /* XXX is was unable to do this port for SPARC64, sorry. (-michi) */
-       /* XXX maybe we need to pass the RA as argument there */
-       vm_abort("codegen_start_native_call: unsupported architecture");
-#endif
-
-       /* get data structures from stack */
-
-       sfi = (stackframeinfo_t *) (datasp - sizeof(stackframeinfo_t));
-       lrt = (localref_table *)   (datasp - sizeof(stackframeinfo_t) - 
-                                                               sizeof(localref_table));
-
-#if defined(ENABLE_JNI)
-       /* add current JNI local references table to this thread */
-
-       localref_table_add(lrt);
-#endif
-
-#if !defined(NDEBUG)
-# if defined(__ALPHA__) || defined(__I386__) || defined(__M68K__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__S390__) || defined(__X86_64__)
-       /* print the call-trace if necesarry */
-       /* BEFORE: filling the local reference table */
-
-       if (opt_TraceJavaCalls)
-               trace_java_call_enter(m, arg_regs, arg_stack);
-# endif
-#endif
-
-#if defined(ENABLE_HANDLES)
-       /* place all references into the local reference table */
-       /* BEFORE: creating stackframeinfo */
-
-       localref_native_enter(m, arg_regs, arg_stack);
-#endif
-
-       /* Add a stackframeinfo for this native method.  We don't have RA
-          and XPC here.  These are determined in
-          stacktrace_stackframeinfo_add. */
-
-       stacktrace_stackframeinfo_add(sfi, pv, sp, NULL, NULL);
-
-       /* Return a wrapped classinfo for static methods. */
-
-       if (m->flags & ACC_STATIC)
-               return (java_handle_t *) LLNI_classinfo_wrap(m->clazz);
-       else
-               return NULL;
-}
-
-
-/* codegen_finish_native_call **************************************************
-
-   Removes the stuff required for a native (JNI) function call.
-   Additionally it checks for an exceptions and in case, get the
-   exception object and clear the pointer.
-
-*******************************************************************************/
-
-java_object_t *codegen_finish_native_call(u1 *sp, u1 *pv)
-{
-       stackframeinfo_t *sfi;
-       java_handle_t    *e;
-       java_object_t    *o;
-       codeinfo         *code;
-       methodinfo       *m;
-       int32_t           framesize;
-
-       uint8_t  *datasp;
-       uint64_t *ret_regs;
-
-       /* get information from method header */
-
-       code = code_get_codeinfo_for_pv(pv);
-
-       framesize = *((int32_t *) (pv + FrameSize));
-
-       assert(code);
-
-       /* get the methodinfo */
-
-       m = code->m;
-       assert(m);
-
-       /* calculate needed values */
-
-#if defined(__ALPHA__) || defined(__ARM__)
-       datasp   = sp + framesize - SIZEOF_VOID_P;
-       ret_regs = (uint64_t *) sp;
-#elif defined(__MIPS__)
-       /* MIPS always uses 8 bytes to store the RA */
-       datasp   = sp + framesize - 8;
-#elif defined(__S390__)
-       datasp   = sp + framesize - 8;
-       ret_regs = (uint64_t *) (sp + 96);
-#elif defined(__I386__)
-       datasp   = sp + framesize;
-       ret_regs = (uint64_t *) (sp + 2 * SIZEOF_VOID_P);
-#elif defined(__M68K__)
-       datasp   = sp + framesize;
-       ret_regs = (uint64_t *) (sp + 2 * 8);
-#elif defined(__X86_64__)
-       datasp   = sp + framesize;
-       ret_regs = (uint64_t *) sp;
-#elif defined(__POWERPC__)
-       datasp   = sp + framesize;
-       ret_regs = (uint64_t *) (sp + LA_SIZE + 2 * SIZEOF_VOID_P);
-#elif defined(__POWERPC64__)
-       datasp   = sp + framesize;
-       ret_regs = (uint64_t *) (sp + PA_SIZE + LA_SIZE + 2 * SIZEOF_VOID_P);
-#else
-       vm_abort("codegen_finish_native_call: unsupported architecture");
-#endif
-
-       /* get data structures from stack */
-
-       sfi = (stackframeinfo_t *) (datasp - sizeof(stackframeinfo_t));
-
-       /* Remove current stackframeinfo from chain. */
-
-       stacktrace_stackframeinfo_remove(sfi);
-
-#if defined(ENABLE_HANDLES)
-       /* unwrap the return value from the local reference table */
-       /* AFTER: removing the stackframeinfo */
-       /* BEFORE: releasing the local reference table */
-
-       localref_native_exit(m, ret_regs);
-#endif
-
-       /* get and unwrap the exception */
-       /* AFTER: removing the stackframe info */
-       /* BEFORE: releasing the local reference table */
-
-       e = exceptions_get_and_clear_exception();
-       o = LLNI_UNWRAP(e);
-
-#if defined(ENABLE_JNI)
-       /* release JNI local references table for this thread */
-
-       localref_frame_pop_all();
-       localref_table_remove();
-#endif
-
-#if !defined(NDEBUG)
-# if defined(__ALPHA__) || defined(__I386__) || defined(__M68K__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__S390__) || defined(__X86_64__)
-       /* print the call-trace if necesarry */
-       /* AFTER: unwrapping the return value */
-
-       if (opt_TraceJavaCalls)
-               trace_java_call_exit(m, ret_regs);
-# endif
-#endif
-
-       return o;
-}
-
-
-/* removecompilerstub **********************************************************
-
-   Deletes a compilerstub from memory (simply by freeing it).
-
-*******************************************************************************/
-
-void removecompilerstub(u1 *stub)
-{
-       /* pass size 1 to keep the intern function happy */
-
-       CFREE((void *) stub, 1);
-}
-
-
-/* removenativestub ************************************************************
-
-   Removes a previously created native-stub from memory.
-    
-*******************************************************************************/
-
-void removenativestub(u1 *stub)
-{
-       /* pass size 1 to keep the intern function happy */
-
-       CFREE((void *) stub, 1);
-}
-
-
-/* codegen_reg_of_var **********************************************************
-
-   This function determines a register, to which the result of an
-   operation should go, when it is ultimatively intended to store the
-   result in pseudoregister v.  If v is assigned to an actual
-   register, this register will be returned.  Otherwise (when v is
-   spilled) this function returns tempregnum.  If not already done,
-   regoff and flags are set in the stack location.
-       
-*******************************************************************************/
-
-s4 codegen_reg_of_var(u2 opcode, varinfo *v, s4 tempregnum)
-{
-       if (!(v->flags & INMEMORY))
-               return v->vv.regoff;
-
-       return tempregnum;
-}
-
-
-/* codegen_reg_of_dst **********************************************************
-
-   This function determines a register, to which the result of an
-   operation should go, when it is ultimatively intended to store the
-   result in iptr->dst.var.  If dst.var is assigned to an actual
-   register, this register will be returned.  Otherwise (when it is
-   spilled) this function returns tempregnum.  If not already done,
-   regoff and flags are set in the stack location.
-       
-*******************************************************************************/
-
-s4 codegen_reg_of_dst(jitdata *jd, instruction *iptr, s4 tempregnum)
-{
-       return codegen_reg_of_var(iptr->opc, VAROP(iptr->dst), tempregnum);
-}
-
-
-/* codegen_emit_phi_moves ****************************************************
-
-   Emits phi moves at the end of the basicblock.
-
-*******************************************************************************/
-
-#if defined(ENABLE_SSA)
-void codegen_emit_phi_moves(jitdata *jd, basicblock *bptr)
-{
-       int lt_d,lt_s,i;
-       lsradata *ls;
-       codegendata *cd;
-       varinfo *s, *d;
-       instruction tmp_i;
-
-       cd = jd->cd;
-       ls = jd->ls;
-
-       MCODECHECK(512);
-
-       /* Moves from phi functions with highest indices have to be */
-       /* inserted first, since this is the order as is used for   */
-       /* conflict resolution */
-
-       for(i = ls->num_phi_moves[bptr->nr] - 1; i >= 0 ; i--) {
-               lt_d = ls->phi_moves[bptr->nr][i][0];
-               lt_s = ls->phi_moves[bptr->nr][i][1];
-#if defined(SSA_DEBUG_VERBOSE)
-               if (compileverbose)
-                       printf("BB %3i Move %3i <- %3i ", bptr->nr, lt_d, lt_s);
-#endif
-               if (lt_s == UNUSED) {
-#if defined(SSA_DEBUG_VERBOSE)
-               if (compileverbose)
-                       printf(" ... not processed \n");
-#endif
-                       continue;
-               }
-                       
-               d = VAR(ls->lifetime[lt_d].v_index);
-               s = VAR(ls->lifetime[lt_s].v_index);
-               
-
-               if (d->type == -1) {
-#if defined(SSA_DEBUG_VERBOSE)
-                       if (compileverbose)
-                               printf("...returning - phi lifetimes where joined\n");
-#endif
-                       continue;
-               }
-
-               if (s->type == -1) {
-#if defined(SSA_DEBUG_VERBOSE)
-                       if (compileverbose)
-                               printf("...returning - phi lifetimes where joined\n");
-#endif
-                       continue;
-               }
-
-               tmp_i.opc = 0;
-               tmp_i.s1.varindex = ls->lifetime[lt_s].v_index;
-               tmp_i.dst.varindex = ls->lifetime[lt_d].v_index;
-               emit_copy(jd, &tmp_i);
-
-#if defined(SSA_DEBUG_VERBOSE)
-               if (compileverbose) {
-                       if (IS_INMEMORY(d->flags) && IS_INMEMORY(s->flags)) {
-                               /* mem -> mem */
-                               printf("M%3i <- M%3i",d->vv.regoff,s->vv.regoff);
-                       }
-                       else if (IS_INMEMORY(s->flags)) {
-                               /* mem -> reg */
-                               printf("R%3i <- M%3i",d->vv.regoff,s->vv.regoff);
-                       }
-                       else if (IS_INMEMORY(d->flags)) {
-                               /* reg -> mem */
-                               printf("M%3i <- R%3i",d->vv.regoff,s->vv.regoff);
-                       }
-                       else {
-                               /* reg -> reg */
-                               printf("R%3i <- R%3i",d->vv.regoff,s->vv.regoff);
-                       }
-                       printf("\n");
-               }
-#endif /* defined(SSA_DEBUG_VERBOSE) */
-       }
-}
-#endif /* defined(ENABLE_SSA) */
-
-
-/* REMOVEME When we have exception handling in C. */
-
-void *md_asm_codegen_get_pv_from_pc(void *ra)
-{
-       return md_codegen_get_pv_from_pc(ra);
-}
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
diff --git a/src/vm/jit/codegen-common.cpp b/src/vm/jit/codegen-common.cpp
new file mode 100644 (file)
index 0000000..1210915
--- /dev/null
@@ -0,0 +1,1081 @@
+/* src/vm/jit/codegen-common.cpp - architecture independent code generator stuff
+
+   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.
+
+   All functions assume the following code area / data area layout:
+
+   +-----------+
+   |           |
+   | code area | code area grows to higher addresses
+   |           |
+   +-----------+ <-- start of procedure
+   |           |
+   | data area | data area grows to lower addresses
+   |           |
+   +-----------+
+
+   The functions first write into a temporary code/data area allocated by
+   "codegen_init". "codegen_finish" copies the code and data area into permanent
+   memory. All functions writing values into the data area return the offset
+   relative the begin of the code area (start of procedure).   
+
+*/
+
+
+#include "config.h"
+
+#include <assert.h>
+#include <string.h>
+
+#include "vm/jit/jitcache.hpp"
+
+#include "vm/types.h"
+
+#include "codegen.h"
+#include "md.h"
+#include "md-abi.h"
+
+#include "mm/memory.h"
+
+#include "toolbox/avl.h"
+#include "toolbox/list.hpp"
+#include "toolbox/logging.h"
+
+#include "native/llni.h"
+#include "native/localref.hpp"
+#include "native/native.hpp"
+
+#include "threads/thread.hpp"
+
+#include "vm/jit/builtin.hpp"
+#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.hpp"
+#include "vm/jit/codegen-common.hpp"
+
+#if defined(ENABLE_DISASSEMBLER)
+# include "vm/jit/disass.h"
+#endif
+
+#include "vm/jit/dseg.h"
+#include "vm/jit/emit-common.hpp"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/linenumbertable.hpp"
+#include "vm/jit/methodheader.h"
+#include "vm/jit/methodtree.h"
+#include "vm/jit/patcher-common.hpp"
+#include "vm/jit/replace.hpp"
+#if defined(ENABLE_SSA)
+# include "vm/jit/optimizing/lsra.h"
+# include "vm/jit/optimizing/ssa.h"
+#endif
+#include "vm/jit/stacktrace.hpp"
+#include "vm/jit/trace.hpp"
+
+#if defined(ENABLE_INTRP)
+#include "vm/jit/intrp/intrp.h"
+#endif
+
+#if defined(ENABLE_VMLOG)
+#include <vmlog_cacao.h>
+#endif
+
+#include "show.hpp"
+
+
+/* codegen_init ****************************************************************
+
+   TODO
+
+*******************************************************************************/
+
+void codegen_init(void)
+{
+}
+
+
+/* codegen_setup ***************************************************************
+
+   Allocates and initialises code area, data area and references.
+
+*******************************************************************************/
+
+void codegen_setup(jitdata *jd)
+{
+       methodinfo  *m;
+       codegendata *cd;
+
+       /* get required compiler data */
+
+       m  = jd->m;
+       cd = jd->cd;
+
+       /* initialize members */
+
+       cd->flags        = 0;
+
+       cd->mcodebase    = (u1*) DumpMemory::allocate(MCODEINITSIZE);
+       cd->mcodeend     = cd->mcodebase + MCODEINITSIZE;
+       cd->mcodesize    = MCODEINITSIZE;
+
+       /* initialize mcode variables */
+
+       cd->mcodeptr     = cd->mcodebase;
+       cd->lastmcodeptr = cd->mcodebase;
+
+#if defined(ENABLE_INTRP)
+       /* native dynamic superinstructions variables */
+
+       if (opt_intrp) {
+               cd->ncodebase = (u1*) DumpMemory::allocate(NCODEINITSIZE);
+               cd->ncodesize = NCODEINITSIZE;
+
+               /* initialize ncode variables */
+       
+               cd->ncodeptr = cd->ncodebase;
+
+               cd->lastinstwithoutdispatch = ~0; /* no inst without dispatch */
+               cd->superstarts = NULL;
+       }
+#endif
+
+       cd->dseg           = NULL;
+       cd->dseglen        = 0;
+
+       cd->jumpreferences = NULL;
+
+#if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
+       cd->datareferences = NULL;
+#endif
+
+       cd->brancheslabel  = new DumpList<branch_label_ref_t*>();
+       cd->linenumbers    = new DumpList<Linenumber>();
+}
+
+
+/* codegen_reset ***************************************************************
+
+   Resets the codegen data structure so we can recompile the method.
+
+*******************************************************************************/
+
+static void codegen_reset(jitdata *jd)
+{
+       codeinfo    *code;
+       codegendata *cd;
+       basicblock  *bptr;
+
+       /* get required compiler data */
+
+       code = jd->code;
+       cd   = jd->cd;
+
+       /* reset error flag */
+
+       cd->flags          &= ~CODEGENDATA_FLAG_ERROR;
+
+       /* reset some members, we reuse the code memory already allocated
+          as this should have almost the correct size */
+
+       cd->mcodeptr        = cd->mcodebase;
+       cd->lastmcodeptr    = cd->mcodebase;
+
+       cd->dseg            = NULL;
+       cd->dseglen         = 0;
+
+       cd->jumpreferences  = NULL;
+
+#if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
+       cd->datareferences  = NULL;
+#endif
+
+       cd->brancheslabel   = new DumpList<branch_label_ref_t*>();
+       cd->linenumbers     = new DumpList<Linenumber>();
+       
+       /* We need to clear the mpc and the branch references from all
+          basic blocks as they will definitely change. */
+
+       for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
+               bptr->mpc        = -1;
+               bptr->branchrefs = NULL;
+       }
+
+       /* We need to clear all the patcher references from the codeinfo
+          since they all will be regenerated */
+
+       patcher_list_reset(code);
+
+#if defined(ENABLE_REPLACEMENT)
+       code->rplpoints     = NULL;
+       code->rplpointcount = 0;
+       code->regalloc      = NULL;
+       code->regalloccount = 0;
+       code->globalcount   = 0;
+#endif
+}
+
+
+/* codegen_generate ************************************************************
+
+   Generates the code for the currently compiled method.
+
+*******************************************************************************/
+
+bool codegen_generate(jitdata *jd)
+{
+       codegendata *cd;
+
+       /* get required compiler data */
+
+       cd = jd->cd;
+
+       /* call the machine-dependent code generation function */
+
+       if (!codegen_emit(jd))
+               return false;
+
+       /* check for an error */
+
+       if (CODEGENDATA_HAS_FLAG_ERROR(cd)) {
+               /* check for long-branches flag, if it is set we recompile the
+                  method */
+
+#if !defined(NDEBUG)
+        if (compileverbose)
+            log_message_method("Re-generating code: ", jd->m);
+#endif
+
+               /* XXX maybe we should tag long-branches-methods for recompilation */
+
+               if (CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
+                       /* we have to reset the codegendata structure first */
+
+                       codegen_reset(jd);
+
+                       /* and restart the compiler run */
+
+                       if (!codegen_emit(jd))
+                               return false;
+               }
+               else {
+                       vm_abort("codegen_generate: unknown error occurred during codegen_emit: flags=%x\n", cd->flags);
+               }
+
+#if !defined(NDEBUG)
+        if (compileverbose)
+            log_message_method("Re-generating code done: ", jd->m);
+#endif
+       }
+
+       /* reallocate the memory and finish the code generation */
+
+       codegen_finish(jd);
+
+       /* everything's ok */
+
+       return true;
+}
+
+
+/* codegen_close ***************************************************************
+
+   TODO
+
+*******************************************************************************/
+
+void codegen_close(void)
+{
+       /* TODO: release avl tree on i386 and x86_64 */
+}
+
+
+/* codegen_increase ************************************************************
+
+   Doubles code area.
+
+*******************************************************************************/
+
+void codegen_increase(codegendata *cd)
+{
+       u1 *oldmcodebase;
+
+       /* save old mcodebase pointer */
+
+       oldmcodebase = cd->mcodebase;
+
+       /* reallocate to new, doubled memory */
+
+       cd->mcodebase = (u1*) DumpMemory::reallocate(cd->mcodebase,
+                                                                                                cd->mcodesize,
+                                                                                                cd->mcodesize * 2);
+       cd->mcodesize *= 2;
+       cd->mcodeend   = cd->mcodebase + cd->mcodesize;
+
+       /* set new mcodeptr */
+
+       cd->mcodeptr = cd->mcodebase + (cd->mcodeptr - oldmcodebase);
+
+#if defined(__I386__) || defined(__MIPS__) || defined(__X86_64__) || defined(__M68K__) || defined(ENABLE_INTRP) \
+ || defined(__SPARC_64__)
+       /* adjust the pointer to the last patcher position */
+
+       if (cd->lastmcodeptr != NULL)
+               cd->lastmcodeptr = cd->mcodebase + (cd->lastmcodeptr - oldmcodebase);
+#endif
+}
+
+
+/* codegen_ncode_increase ******************************************************
+
+   Doubles code area.
+
+*******************************************************************************/
+
+#if defined(ENABLE_INTRP)
+u1 *codegen_ncode_increase(codegendata *cd, u1 *ncodeptr)
+{
+       u1 *oldncodebase;
+
+       /* save old ncodebase pointer */
+
+       oldncodebase = cd->ncodebase;
+
+       /* reallocate to new, doubled memory */
+
+       cd->ncodebase = DMREALLOC(cd->ncodebase,
+                                                         u1,
+                                                         cd->ncodesize,
+                                                         cd->ncodesize * 2);
+       cd->ncodesize *= 2;
+
+       /* return the new ncodeptr */
+
+       return (cd->ncodebase + (ncodeptr - oldncodebase));
+}
+#endif
+
+
+/* codegen_add_branch_ref ******************************************************
+
+   Prepends an branch to the list.
+
+*******************************************************************************/
+
+void codegen_add_branch_ref(codegendata *cd, basicblock *target, s4 condition, s4 reg, u4 options)
+{
+       branchref *br;
+       s4         branchmpc;
+
+       STATISTICS(count_branches_unresolved++);
+
+       /* calculate the mpc of the branch instruction */
+
+       branchmpc = cd->mcodeptr - cd->mcodebase;
+
+       br = (branchref*) DumpMemory::allocate(sizeof(branchref));
+
+       br->branchmpc = branchmpc;
+       br->condition = condition;
+       br->reg       = reg;
+       br->options   = options;
+       br->next      = target->branchrefs;
+
+       target->branchrefs = br;
+}
+
+
+/* codegen_resolve_branchrefs **************************************************
+
+   Resolves and patches the branch references of a given basic block.
+
+*******************************************************************************/
+
+void codegen_resolve_branchrefs(codegendata *cd, basicblock *bptr)
+{
+       branchref *br;
+       u1        *mcodeptr;
+
+       /* Save the mcodeptr because in the branch emitting functions
+          we generate code somewhere inside already generated code,
+          but we're still in the actual code generation phase. */
+
+       mcodeptr = cd->mcodeptr;
+
+       /* just to make sure */
+
+       assert(bptr->mpc >= 0);
+
+       for (br = bptr->branchrefs; br != NULL; br = br->next) {
+               /* temporary set the mcodeptr */
+
+               cd->mcodeptr = cd->mcodebase + br->branchmpc;
+
+               /* emit_bccz and emit_branch emit the correct code, even if we
+                  pass condition == BRANCH_UNCONDITIONAL or reg == -1. */
+
+               emit_bccz(cd, bptr, br->condition, br->reg, br->options);
+       }
+
+       /* restore mcodeptr */
+
+       cd->mcodeptr = mcodeptr;
+}
+
+
+/* codegen_branch_label_add ****************************************************
+
+   Append an branch to the label-branch list.
+
+*******************************************************************************/
+
+void codegen_branch_label_add(codegendata *cd, s4 label, s4 condition, s4 reg, u4 options)
+{
+       // Calculate the current mpc.
+       int32_t mpc = cd->mcodeptr - cd->mcodebase;
+
+       branch_label_ref_t* br = (branch_label_ref_t*) DumpMemory::allocate(sizeof(branch_label_ref_t));
+
+       br->mpc       = mpc;
+       br->label     = label;
+       br->condition = condition;
+       br->reg       = reg;
+       br->options   = options;
+
+       // Add the branch to the list.
+       cd->brancheslabel->push_back(br);
+}
+
+
+/* codegen_set_replacement_point_notrap ****************************************
+
+   Record the position of a non-trappable replacement point.
+
+*******************************************************************************/
+
+#if defined(ENABLE_REPLACEMENT)
+#if !defined(NDEBUG)
+void codegen_set_replacement_point_notrap(codegendata *cd, s4 type)
+#else
+void codegen_set_replacement_point_notrap(codegendata *cd)
+#endif
+{
+       assert(cd->replacementpoint);
+       assert(cd->replacementpoint->type == type);
+       assert(cd->replacementpoint->flags & RPLPOINT_FLAG_NOTRAP);
+
+       cd->replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
+
+       cd->replacementpoint++;
+}
+#endif /* defined(ENABLE_REPLACEMENT) */
+
+
+/* codegen_set_replacement_point ***********************************************
+
+   Record the position of a trappable replacement point.
+
+*******************************************************************************/
+
+#if defined(ENABLE_REPLACEMENT)
+#if !defined(NDEBUG)
+void codegen_set_replacement_point(codegendata *cd, s4 type)
+#else
+void codegen_set_replacement_point(codegendata *cd)
+#endif
+{
+       assert(cd->replacementpoint);
+       assert(cd->replacementpoint->type == type);
+       assert(!(cd->replacementpoint->flags & RPLPOINT_FLAG_NOTRAP));
+
+       cd->replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
+
+       cd->replacementpoint++;
+
+#if !defined(NDEBUG)
+       /* XXX actually we should use an own REPLACEMENT_NOPS here! */
+       if (opt_TestReplacement)
+               PATCHER_NOPS;
+#endif
+
+       /* XXX assert(cd->lastmcodeptr <= cd->mcodeptr); */
+
+       cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
+}
+#endif /* defined(ENABLE_REPLACEMENT) */
+
+
+/* codegen_finish **************************************************************
+
+   Finishes the code generation. A new memory, large enough for both
+   data and code, is allocated and data and code are copied together
+   to their final layout, unresolved jumps are resolved, ...
+
+*******************************************************************************/
+
+void codegen_finish(jitdata *jd)
+{
+       codeinfo    *code;
+       codegendata *cd;
+       s4           mcodelen;
+#if defined(ENABLE_INTRP)
+       s4           ncodelen;
+#endif
+       s4           alignedmcodelen;
+       jumpref     *jr;
+       u1          *epoint;
+       s4           alignedlen;
+
+       /* get required compiler data */
+
+       code = jd->code;
+       cd   = jd->cd;
+
+       /* prevent compiler warning */
+
+#if defined(ENABLE_INTRP)
+       ncodelen = 0;
+#endif
+
+       /* calculate the code length */
+
+       mcodelen = (s4) (cd->mcodeptr - cd->mcodebase);
+
+#if defined(ENABLE_STATISTICS)
+       if (opt_stat) {
+               count_code_len += mcodelen;
+               count_data_len += cd->dseglen;
+       }
+#endif
+
+       alignedmcodelen = MEMORY_ALIGN(mcodelen, MAX_ALIGN);
+
+#if defined(ENABLE_INTRP)
+       if (opt_intrp)
+               ncodelen = cd->ncodeptr - cd->ncodebase;
+       else {
+               ncodelen = 0; /* avoid compiler warning */
+       }
+#endif
+
+       cd->dseglen = MEMORY_ALIGN(cd->dseglen, MAX_ALIGN);
+       alignedlen = alignedmcodelen + cd->dseglen;
+
+#if defined(ENABLE_INTRP)
+       if (opt_intrp) {
+               alignedlen += ncodelen;
+       }
+#endif
+
+       /* allocate new memory */
+
+       code->mcodelength = mcodelen + cd->dseglen;
+       code->mcode       = CNEW(u1, alignedlen);
+
+       /* set the entrypoint of the method */
+       
+       assert(code->entrypoint == NULL);
+       code->entrypoint = epoint = (code->mcode + cd->dseglen);
+
+       /* fill the data segment (code->entrypoint must already be set!) */
+
+       dseg_finish(jd);
+
+       /* copy code to the new location */
+
+       MCOPY((void *) code->entrypoint, cd->mcodebase, u1, mcodelen);
+
+#if defined(ENABLE_INTRP)
+       /* relocate native dynamic superinstruction code (if any) */
+
+       if (opt_intrp) {
+               cd->mcodebase = code->entrypoint;
+
+               if (ncodelen > 0) {
+                       u1 *ncodebase = code->mcode + cd->dseglen + alignedmcodelen;
+
+                       MCOPY((void *) ncodebase, cd->ncodebase, u1, ncodelen);
+
+                       /* flush the instruction and data caches */
+
+                       md_cacheflush(ncodebase, ncodelen);
+
+                       /* set some cd variables for dynamic_super_rerwite */
+
+                       cd->ncodebase = ncodebase;
+
+               } else {
+                       cd->ncodebase = NULL;
+               }
+
+               dynamic_super_rewrite(cd);
+       }
+#endif
+
+       /* Create the exception table. */
+
+       exceptiontable_create(jd);
+
+       /* Create the linenumber table. */
+
+       code->linenumbertable = new LinenumberTable(jd);
+
+       /* jump table resolving */
+
+       for (jr = cd->jumpreferences; jr != NULL; jr = jr->next)
+       {
+               *((functionptr *) ((ptrint) epoint + jr->tablepos)) =
+                       (functionptr) ((ptrint) epoint + (ptrint) jr->target->mpc);
+
+               JITCACHE_ADD_CACHED_REF(code, CRT_JUMPREFERENCE, jr->target->mpc, jr->tablepos);
+       }
+
+       /* patcher resolving */
+
+       patcher_resolve(jd);
+
+#if defined(ENABLE_REPLACEMENT)
+       /* replacement point resolving */
+       {
+               int i;
+               rplpoint *rp;
+
+               rp = code->rplpoints;
+               for (i=0; i<code->rplpointcount; ++i, ++rp) {
+                       rp->pc = (u1*) ((ptrint) epoint + (ptrint) rp->pc);
+               }
+       }
+#endif /* defined(ENABLE_REPLACEMENT) */
+
+       /* Insert method into methodtree to find the entrypoint. */
+
+       methodtree_insert(code->entrypoint, code->entrypoint + mcodelen);
+
+#if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
+       /* resolve data segment references */
+
+       dseg_resolve_datareferences(jd);
+#endif
+
+       /* flush the instruction and data caches */
+
+       md_cacheflush(code->mcode, code->mcodelength);
+}
+
+
+/* codegen_start_native_call ***************************************************
+
+   Prepares the stuff required for a native (JNI) function call:
+
+   - adds a stackframe info structure to the chain, for stacktraces
+   - prepares the local references table on the stack
+
+   The layout of the native stub stackframe should look like this:
+
+   +---------------------------+ <- java SP (of parent Java function)
+   | return address            |
+   +---------------------------+ <- data SP
+   |                           |
+   | stackframe info structure |
+   |                           |
+   +---------------------------+
+   |                           |
+   | local references table    |
+   |                           |
+   +---------------------------+
+   |                           |
+   | saved registers (if any)  |
+   |                           |
+   +---------------------------+
+   |                           |
+   | arguments (if any)        |
+   |                           |
+   +---------------------------+ <- current SP (native stub)
+
+*******************************************************************************/
+
+java_handle_t *codegen_start_native_call(u1 *sp, u1 *pv)
+{
+       stackframeinfo_t *sfi;
+       localref_table   *lrt;
+       methodinfo       *m;
+       int32_t           framesize;
+
+       uint8_t  *datasp;
+       uint8_t  *javasp;
+       uint64_t *arg_regs;
+       uint64_t *arg_stack;
+
+       STATISTICS(count_calls_java_to_native++);
+
+       /* Get the methodinfo. */
+
+       m = code_get_methodinfo_for_pv(pv);
+
+       assert(m);
+
+       framesize = *((int32_t *) (pv + FrameSize));
+
+       assert(framesize >= (int32_t) (sizeof(stackframeinfo_t) + sizeof(localref_table)));
+
+       /* calculate needed values */
+
+#if defined(__ALPHA__) || defined(__ARM__)
+       datasp    = sp + framesize - SIZEOF_VOID_P;
+       javasp    = sp + framesize;
+       arg_regs  = (uint64_t *) sp;
+       arg_stack = (uint64_t *) javasp;
+#elif defined(__MIPS__)
+       /* MIPS always uses 8 bytes to store the RA */
+       datasp    = sp + framesize - 8;
+       javasp    = sp + framesize;
+#elif defined(__S390__)
+       datasp    = sp + framesize - 8;
+       javasp    = sp + framesize;
+       arg_regs  = (uint64_t *) (sp + 96);
+       arg_stack = (uint64_t *) javasp;
+#elif defined(__I386__) || defined(__M68K__) || defined(__X86_64__)
+       datasp    = sp + framesize;
+       javasp    = sp + framesize + SIZEOF_VOID_P;
+       arg_regs  = (uint64_t *) sp;
+       arg_stack = (uint64_t *) javasp;
+#elif defined(__POWERPC__)
+       datasp    = sp + framesize;
+       javasp    = sp + framesize;
+       arg_regs  = (uint64_t *) (sp + LA_SIZE + 4 * SIZEOF_VOID_P);
+       arg_stack = (uint64_t *) javasp;
+#elif defined(__POWERPC64__)
+       datasp    = sp + framesize;
+       javasp    = sp + framesize;
+       arg_regs  = (uint64_t *) (sp + PA_SIZE + LA_SIZE + 4 * SIZEOF_VOID_P);
+       arg_stack = (uint64_t *) javasp;
+#else
+       /* XXX is was unable to do this port for SPARC64, sorry. (-michi) */
+       /* XXX maybe we need to pass the RA as argument there */
+       vm_abort("codegen_start_native_call: unsupported architecture");
+#endif
+
+       /* get data structures from stack */
+
+       sfi = (stackframeinfo_t *) (datasp - sizeof(stackframeinfo_t));
+       lrt = (localref_table *)   (datasp - sizeof(stackframeinfo_t) - 
+                                                               sizeof(localref_table));
+
+#if defined(ENABLE_JNI)
+       /* add current JNI local references table to this thread */
+
+       localref_table_add(lrt);
+#endif
+
+#if !defined(NDEBUG)
+# if defined(__ALPHA__) || defined(__I386__) || defined(__M68K__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__S390__) || defined(__X86_64__)
+       /* print the call-trace if necesarry */
+       /* BEFORE: filling the local reference table */
+
+       if (opt_TraceJavaCalls)
+               trace_java_call_enter(m, arg_regs, arg_stack);
+# endif
+#endif
+
+#if defined(ENABLE_HANDLES)
+       /* place all references into the local reference table */
+       /* BEFORE: creating stackframeinfo */
+
+       localref_native_enter(m, arg_regs, arg_stack);
+#endif
+
+       /* Add a stackframeinfo for this native method.  We don't have RA
+          and XPC here.  These are determined in
+          stacktrace_stackframeinfo_add. */
+
+       stacktrace_stackframeinfo_add(sfi, pv, sp, NULL, NULL);
+
+       /* Return a wrapped classinfo for static methods. */
+
+       if (m->flags & ACC_STATIC)
+               return (java_handle_t *) LLNI_classinfo_wrap(m->clazz);
+       else
+               return NULL;
+}
+
+
+/* codegen_finish_native_call **************************************************
+
+   Removes the stuff required for a native (JNI) function call.
+   Additionally it checks for an exceptions and in case, get the
+   exception object and clear the pointer.
+
+*******************************************************************************/
+
+java_object_t *codegen_finish_native_call(u1 *sp, u1 *pv)
+{
+       stackframeinfo_t *sfi;
+       java_handle_t    *e;
+       java_object_t    *o;
+       codeinfo         *code;
+       methodinfo       *m;
+       int32_t           framesize;
+
+       uint8_t  *datasp;
+       uint64_t *ret_regs;
+
+       /* get information from method header */
+
+       code = code_get_codeinfo_for_pv(pv);
+
+       framesize = *((int32_t *) (pv + FrameSize));
+
+       assert(code);
+
+       /* get the methodinfo */
+
+       m = code->m;
+       assert(m);
+
+       /* calculate needed values */
+
+#if defined(__ALPHA__) || defined(__ARM__)
+       datasp   = sp + framesize - SIZEOF_VOID_P;
+       ret_regs = (uint64_t *) sp;
+#elif defined(__MIPS__)
+       /* MIPS always uses 8 bytes to store the RA */
+       datasp   = sp + framesize - 8;
+#elif defined(__S390__)
+       datasp   = sp + framesize - 8;
+       ret_regs = (uint64_t *) (sp + 96);
+#elif defined(__I386__)
+       datasp   = sp + framesize;
+       ret_regs = (uint64_t *) (sp + 2 * SIZEOF_VOID_P);
+#elif defined(__M68K__)
+       datasp   = sp + framesize;
+       ret_regs = (uint64_t *) (sp + 2 * 8);
+#elif defined(__X86_64__)
+       datasp   = sp + framesize;
+       ret_regs = (uint64_t *) sp;
+#elif defined(__POWERPC__)
+       datasp   = sp + framesize;
+       ret_regs = (uint64_t *) (sp + LA_SIZE + 2 * SIZEOF_VOID_P);
+#elif defined(__POWERPC64__)
+       datasp   = sp + framesize;
+       ret_regs = (uint64_t *) (sp + PA_SIZE + LA_SIZE + 2 * SIZEOF_VOID_P);
+#else
+       vm_abort("codegen_finish_native_call: unsupported architecture");
+#endif
+
+       /* get data structures from stack */
+
+       sfi = (stackframeinfo_t *) (datasp - sizeof(stackframeinfo_t));
+
+       /* Remove current stackframeinfo from chain. */
+
+       stacktrace_stackframeinfo_remove(sfi);
+
+#if defined(ENABLE_HANDLES)
+       /* unwrap the return value from the local reference table */
+       /* AFTER: removing the stackframeinfo */
+       /* BEFORE: releasing the local reference table */
+
+       localref_native_exit(m, ret_regs);
+#endif
+
+       /* get and unwrap the exception */
+       /* AFTER: removing the stackframe info */
+       /* BEFORE: releasing the local reference table */
+
+       e = exceptions_get_and_clear_exception();
+       o = LLNI_UNWRAP(e);
+
+#if defined(ENABLE_JNI)
+       /* release JNI local references table for this thread */
+
+       localref_frame_pop_all();
+       localref_table_remove();
+#endif
+
+#if !defined(NDEBUG)
+# if defined(__ALPHA__) || defined(__I386__) || defined(__M68K__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__S390__) || defined(__X86_64__)
+       /* print the call-trace if necesarry */
+       /* AFTER: unwrapping the return value */
+
+       if (opt_TraceJavaCalls)
+               trace_java_call_exit(m, ret_regs);
+# endif
+#endif
+
+       return o;
+}
+
+
+/* codegen_reg_of_var **********************************************************
+
+   This function determines a register, to which the result of an
+   operation should go, when it is ultimatively intended to store the
+   result in pseudoregister v.  If v is assigned to an actual
+   register, this register will be returned.  Otherwise (when v is
+   spilled) this function returns tempregnum.  If not already done,
+   regoff and flags are set in the stack location.
+       
+*******************************************************************************/
+
+s4 codegen_reg_of_var(u2 opcode, varinfo *v, s4 tempregnum)
+{
+       if (!(v->flags & INMEMORY))
+               return v->vv.regoff;
+
+       return tempregnum;
+}
+
+
+/* codegen_reg_of_dst **********************************************************
+
+   This function determines a register, to which the result of an
+   operation should go, when it is ultimatively intended to store the
+   result in iptr->dst.var.  If dst.var is assigned to an actual
+   register, this register will be returned.  Otherwise (when it is
+   spilled) this function returns tempregnum.  If not already done,
+   regoff and flags are set in the stack location.
+       
+*******************************************************************************/
+
+s4 codegen_reg_of_dst(jitdata *jd, instruction *iptr, s4 tempregnum)
+{
+       return codegen_reg_of_var(iptr->opc, VAROP(iptr->dst), tempregnum);
+}
+
+
+/* codegen_emit_phi_moves ****************************************************
+
+   Emits phi moves at the end of the basicblock.
+
+*******************************************************************************/
+
+#if defined(ENABLE_SSA)
+void codegen_emit_phi_moves(jitdata *jd, basicblock *bptr)
+{
+       int lt_d,lt_s,i;
+       lsradata *ls;
+       codegendata *cd;
+       varinfo *s, *d;
+       instruction tmp_i;
+
+       cd = jd->cd;
+       ls = jd->ls;
+
+       MCODECHECK(512);
+
+       /* Moves from phi functions with highest indices have to be */
+       /* inserted first, since this is the order as is used for   */
+       /* conflict resolution */
+
+       for(i = ls->num_phi_moves[bptr->nr] - 1; i >= 0 ; i--) {
+               lt_d = ls->phi_moves[bptr->nr][i][0];
+               lt_s = ls->phi_moves[bptr->nr][i][1];
+#if defined(SSA_DEBUG_VERBOSE)
+               if (compileverbose)
+                       printf("BB %3i Move %3i <- %3i ", bptr->nr, lt_d, lt_s);
+#endif
+               if (lt_s == UNUSED) {
+#if defined(SSA_DEBUG_VERBOSE)
+               if (compileverbose)
+                       printf(" ... not processed \n");
+#endif
+                       continue;
+               }
+                       
+               d = VAR(ls->lifetime[lt_d].v_index);
+               s = VAR(ls->lifetime[lt_s].v_index);
+               
+
+               if (d->type == -1) {
+#if defined(SSA_DEBUG_VERBOSE)
+                       if (compileverbose)
+                               printf("...returning - phi lifetimes where joined\n");
+#endif
+                       continue;
+               }
+
+               if (s->type == -1) {
+#if defined(SSA_DEBUG_VERBOSE)
+                       if (compileverbose)
+                               printf("...returning - phi lifetimes where joined\n");
+#endif
+                       continue;
+               }
+
+               tmp_i.opc = 0;
+               tmp_i.s1.varindex = ls->lifetime[lt_s].v_index;
+               tmp_i.dst.varindex = ls->lifetime[lt_d].v_index;
+               emit_copy(jd, &tmp_i);
+
+#if defined(SSA_DEBUG_VERBOSE)
+               if (compileverbose) {
+                       if (IS_INMEMORY(d->flags) && IS_INMEMORY(s->flags)) {
+                               /* mem -> mem */
+                               printf("M%3i <- M%3i",d->vv.regoff,s->vv.regoff);
+                       }
+                       else if (IS_INMEMORY(s->flags)) {
+                               /* mem -> reg */
+                               printf("R%3i <- M%3i",d->vv.regoff,s->vv.regoff);
+                       }
+                       else if (IS_INMEMORY(d->flags)) {
+                               /* reg -> mem */
+                               printf("M%3i <- R%3i",d->vv.regoff,s->vv.regoff);
+                       }
+                       else {
+                               /* reg -> reg */
+                               printf("R%3i <- R%3i",d->vv.regoff,s->vv.regoff);
+                       }
+                       printf("\n");
+               }
+#endif /* defined(SSA_DEBUG_VERBOSE) */
+       }
+}
+#endif /* defined(ENABLE_SSA) */
+
+
+/* REMOVEME When we have exception handling in C. */
+
+void *md_asm_codegen_get_pv_from_pc(void *ra)
+{
+       return md_codegen_get_pv_from_pc(ra);
+}
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
diff --git a/src/vm/jit/codegen-common.h b/src/vm/jit/codegen-common.h
deleted file mode 100644 (file)
index 4a4fea9..0000000
+++ /dev/null
@@ -1,298 +0,0 @@
-/* src/vm/jit/codegen-common.h - architecture independent code generator stuff
-
-   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 _CODEGEN_COMMON_H
-#define _CODEGEN_COMMON_H
-
-/* forward typedefs ***********************************************************/
-
-typedef struct codegendata            codegendata;
-typedef struct branchref              branchref;
-typedef struct branch_label_ref_t     branch_label_ref_t;
-typedef struct jumpref                jumpref;
-typedef struct dataref                dataref;
-typedef struct exceptionref           exceptionref;
-typedef struct linenumberref          linenumberref;
-
-
-#include "config.h"
-#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/reg.h"
-#include "vm/jit/code.h"
-#include "vm/jit/replace.h"
-
-
-#define MCODEINITSIZE (1<<15)       /* 32 Kbyte code area initialization size */
-#define DSEGINITSIZE  (1<<12)       /*  4 Kbyte data area initialization size */
-
-#define NCODEINITSIZE (1<<15)       /* 32 Kbyte code area initialization size */
-
-
-/* Register Pack/Unpack Macros ************************************************/
-
-/* ATTENTION: Don't change the order where low and high bits are
-   stored! At least mips32 relies in one case on that order. */
-
-#define PACK_REGS(low,high) \
-    ( (((high) & 0x0000ffff) << 16) | ((low) & 0x0000ffff) )
-
-#define GET_LOW_REG(a)      ((a) & 0x0000ffff)
-#define GET_HIGH_REG(a)    (((a) & 0xffff0000) >> 16)
-
-
-/* branch conditions **********************************************************/
-
-#define BRANCH_UNCONDITIONAL    -1
-
-#define BRANCH_EQ               (ICMD_IFEQ - ICMD_IFEQ)
-#define BRANCH_NE               (ICMD_IFNE - ICMD_IFEQ)
-#define BRANCH_LT               (ICMD_IFLT - ICMD_IFEQ)
-#define BRANCH_GE               (ICMD_IFGE - ICMD_IFEQ)
-#define BRANCH_GT               (ICMD_IFGT - ICMD_IFEQ)
-#define BRANCH_LE               (ICMD_IFLE - ICMD_IFEQ)
-
-#define BRANCH_ULT              256
-#define BRANCH_ULE              257
-#define BRANCH_UGE              258
-#define BRANCH_UGT              259
-
-#define BRANCH_NAN              260
-
-
-/* common branch options ******************************************************/
-
-#define BRANCH_OPT_NONE         0
-
-
-/* codegendata ****************************************************************/
-
-struct codegendata {
-       u4              flags;          /* code generator flags                   */
-       u1             *mcodebase;      /* base pointer of code area              */
-       u1             *mcodeend;       /* pointer to end of code area            */
-       s4              mcodesize;      /* complete size of code area (bytes)     */
-       u1             *mcodeptr;       /* code generation pointer                */
-       u1             *lastmcodeptr;   /* last patcher position of basic block   */
-
-#if defined(ENABLE_INTRP)
-       u1             *ncodebase;      /* base pointer of native code area       */
-       s4              ncodesize;      /* complete size of native code area      */
-       u1             *ncodeptr;       /* native code generation pointer         */
-
-       u4              lastinstwithoutdispatch; /* ~0 if there was a dispatch    */
-
-       s4              lastpatcheroffset; /* -1 if current super has no patcher  */
-       s4              dynsuperm;      /* offsets of start of current dynamic ...*/
-       s4              dynsupern;      /* ... superinstruction starts            */
-       struct superstart *superstarts; /* list of supers without patchers        */
-#endif
-
-       dsegentry      *dseg;           /* chain of data segment entries          */
-       s4              dseglen;        /* used size of data area (bytes)         */
-                                    /* data area grows from top to bottom     */
-
-       jumpref        *jumpreferences; /* list of jumptable target addresses     */
-
-#if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP) || defined(__S390__)
-       dataref        *datareferences; /* list of data segment references        */
-#endif
-
-       list_t         *brancheslabel;
-       list_t         *linenumbers;    /* list of line numbers                   */
-
-       methodinfo     *method;
-
-       s4              stackframesize;    /* stackframe size of this method      */
-
-#if defined(ENABLE_REPLACEMENT)
-       rplpoint       *replacementpoint;  /* current replacement point           */
-#endif
-};
-
-
-#define CODEGENDATA_FLAG_ERROR           0x00000001
-#define CODEGENDATA_FLAG_LONGBRANCHES    0x00000002
-
-
-#define CODEGENDATA_HAS_FLAG_ERROR(cd) \
-    ((cd)->flags & CODEGENDATA_FLAG_ERROR)
-
-#define CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd) \
-    ((cd)->flags & CODEGENDATA_FLAG_LONGBRANCHES)
-
-
-/* branchref *****************************************************************/
-
-struct branchref {
-       s4         branchmpc;       /* patching position in code segment          */
-       s4         condition;       /* conditional branch condition               */
-       s4         reg;             /* register number to check                   */
-       u4         options;         /* branch options                             */
-       branchref *next;            /* next element in branchref list             */
-};
-
-
-/* branch_label_ref_t *********************************************************/
-
-struct branch_label_ref_t {
-       s4         mpc;             /* position in code segment                   */
-       s4         label;           /* label number                               */
-       s4         condition;       /* conditional branch condition               */
-       s4         reg;             /* register number to check                   */
-       u4         options;         /* branch options                             */
-       listnode_t linkage;
-};
-
-
-/* jumpref ********************************************************************/
-
-struct jumpref {
-       s4          tablepos;       /* patching position in data segment          */
-       basicblock *target;         /* target basic block                         */
-       jumpref    *next;           /* next element in jumpref list               */
-};
-
-
-/* dataref ********************************************************************/
-
-struct dataref {
-       s4       datapos;           /* patching position in generated code        */
-       dataref *next;              /* next element in dataref list               */
-};
-
-
-/* linenumberref **************************************************************/
-
-struct linenumberref {
-       s4             tablepos;    /* patching position in data segment          */
-       s4             linenumber;  /* line number, used for inserting into the   */
-                                   /* table and for validity checking            */
-                                   /* -1......start of inlined body              */
-                                   /* -2......end of inlined body                */
-                                   /* <= -3...special entry with methodinfo *    */
-                                                               /* (see doc/inlining_stacktrace.txt)          */
-       ptrint         targetmpc;   /* machine code program counter of first      */
-                                   /* instruction for given line                 */
-                                                               /* NOTE: for linenumber <= -3 this is a the   */
-                                   /* (methodinfo *) of the inlined method       */
-       linenumberref *next;        /* next element in linenumberref list         */
-};
-
-
-/* function prototypes ********************************************************/
-
-void codegen_init(void);
-void codegen_setup(jitdata *jd);
-
-bool codegen_generate(jitdata *jd);
-bool codegen_emit(jitdata *jd);
-
-#if defined(ENABLE_INTRP)
-bool intrp_codegen(jitdata *jd);
-#endif
-
-void codegen_close(void);
-
-void codegen_increase(codegendata *cd);
-
-#if defined(ENABLE_INTRP)
-u1 *codegen_ncode_increase(codegendata *cd, u1 *ncodeptr);
-#endif
-
-void codegen_add_branch_ref(codegendata *cd, basicblock *target, s4 condition, s4 reg, u4 options);
-void codegen_resolve_branchrefs(codegendata *cd, basicblock *bptr);
-
-void codegen_branch_label_add(codegendata *cd, s4 label, s4 condition, s4 reg, u4 options);
-
-#if defined(ENABLE_REPLACEMENT)
-#if !defined(NDEBUG)
-void codegen_set_replacement_point_notrap(codegendata *cd, s4 type);
-void codegen_set_replacement_point(codegendata *cd, s4 type);
-#else
-void codegen_set_replacement_point_notrap(codegendata *cd);
-void codegen_set_replacement_point(codegendata *cd);
-#endif
-#endif /* defined(ENABLE_REPLACEMENT) */
-
-void codegen_finish(jitdata *jd);
-
-#if defined(ENABLE_DISASSEMBLER)
-void codegen_disassemble_stub(methodinfo *m, u1 *start, u1 *end);
-#endif
-
-/* stub functions */
-
-u1       *codegen_generate_stub_compiler(methodinfo *m);
-void      codegen_generate_stub_builtin(methodinfo *m, builtintable_entry *bte);
-codeinfo *codegen_generate_stub_native(methodinfo *m, functionptr f);
-
-#if !defined(JIT_COMPILER_VIA_SIGNAL)
-void      codegen_emit_stub_compiler(jitdata *jd);
-#endif
-void      codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int skipparams);
-
-#if defined(ENABLE_INTRP)
-u1 *intrp_createcompilerstub(methodinfo *m);
-u1 *intrp_createnativestub(functionptr f, jitdata *jd, methoddesc *md);
-#endif
-
-void removecompilerstub(u1 *stub);
-void removenativestub(u1 *stub);
-
-java_handle_t *codegen_start_native_call(u1 *currentsp, u1 *pv);
-java_object_t *codegen_finish_native_call(u1 *currentsp, u1 *pv);
-
-s4 codegen_reg_of_var(u2 opcode, varinfo *v, s4 tempregnum);
-s4 codegen_reg_of_dst(jitdata *jd, instruction *iptr, s4 tempregnum);
-
-#if defined(ENABLE_SSA)
-void codegen_emit_phi_moves(jitdata *jd, basicblock *bptr);
-#endif
-
-#endif /* _CODEGEN_COMMON_H */
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
diff --git a/src/vm/jit/codegen-common.hpp b/src/vm/jit/codegen-common.hpp
new file mode 100644 (file)
index 0000000..8e676a4
--- /dev/null
@@ -0,0 +1,276 @@
+/* src/vm/jit/codegen-common.hpp - architecture independent code generator stuff
+
+   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 _CODEGEN_COMMON_HPP
+#define _CODEGEN_COMMON_HPP
+
+/* forward typedefs ***********************************************************/
+
+typedef struct codegendata            codegendata;
+typedef struct branchref              branchref;
+typedef struct branch_label_ref_t     branch_label_ref_t;
+typedef struct jumpref                jumpref;
+typedef struct dataref                dataref;
+
+
+#include "config.h"
+#include "vm/types.h"
+
+#include "toolbox/list.hpp"
+
+#include "vm/jit/builtin.hpp"
+#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.hpp"
+#include "vm/jit/reg.h"
+#include "vm/jit/code.hpp"
+#include "vm/jit/linenumbertable.hpp"
+#include "vm/jit/replace.hpp"
+
+
+#define MCODEINITSIZE (1<<15)       /* 32 Kbyte code area initialization size */
+#define DSEGINITSIZE  (1<<12)       /*  4 Kbyte data area initialization size */
+
+#define NCODEINITSIZE (1<<15)       /* 32 Kbyte code area initialization size */
+
+
+/* Register Pack/Unpack Macros ************************************************/
+
+/* ATTENTION: Don't change the order where low and high bits are
+   stored! At least mips32 relies in one case on that order. */
+
+#define PACK_REGS(low,high) \
+    ( (((high) & 0x0000ffff) << 16) | ((low) & 0x0000ffff) )
+
+#define GET_LOW_REG(a)      ((a) & 0x0000ffff)
+#define GET_HIGH_REG(a)    (((a) & 0xffff0000) >> 16)
+
+
+/* branch conditions **********************************************************/
+
+#define BRANCH_UNCONDITIONAL    -1
+
+#define BRANCH_EQ               (ICMD_IFEQ - ICMD_IFEQ)
+#define BRANCH_NE               (ICMD_IFNE - ICMD_IFEQ)
+#define BRANCH_LT               (ICMD_IFLT - ICMD_IFEQ)
+#define BRANCH_GE               (ICMD_IFGE - ICMD_IFEQ)
+#define BRANCH_GT               (ICMD_IFGT - ICMD_IFEQ)
+#define BRANCH_LE               (ICMD_IFLE - ICMD_IFEQ)
+
+#define BRANCH_ULT              256
+#define BRANCH_ULE              257
+#define BRANCH_UGE              258
+#define BRANCH_UGT              259
+
+#define BRANCH_NAN              260
+
+
+/* common branch options ******************************************************/
+
+#define BRANCH_OPT_NONE         0
+
+
+/* codegendata ****************************************************************/
+
+struct codegendata {
+       u4              flags;          /* code generator flags                   */
+       u1             *mcodebase;      /* base pointer of code area              */
+       u1             *mcodeend;       /* pointer to end of code area            */
+       s4              mcodesize;      /* complete size of code area (bytes)     */
+       u1             *mcodeptr;       /* code generation pointer                */
+       u1             *lastmcodeptr;   /* last patcher position of basic block   */
+
+#if defined(ENABLE_INTRP)
+       u1             *ncodebase;      /* base pointer of native code area       */
+       s4              ncodesize;      /* complete size of native code area      */
+       u1             *ncodeptr;       /* native code generation pointer         */
+
+       u4              lastinstwithoutdispatch; /* ~0 if there was a dispatch    */
+
+       s4              lastpatcheroffset; /* -1 if current super has no patcher  */
+       s4              dynsuperm;      /* offsets of start of current dynamic ...*/
+       s4              dynsupern;      /* ... superinstruction starts            */
+       struct superstart *superstarts; /* list of supers without patchers        */
+#endif
+
+       dsegentry      *dseg;           /* chain of data segment entries          */
+       s4              dseglen;        /* used size of data area (bytes)         */
+                                    /* data area grows from top to bottom     */
+
+       jumpref        *jumpreferences; /* list of jumptable target addresses     */
+
+#if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP) || defined(__S390__)
+       dataref        *datareferences; /* list of data segment references        */
+#endif
+
+#ifdef __cplusplus
+       DumpList<branch_label_ref_t*>* brancheslabel;
+       DumpList<Linenumber>* linenumbers; ///< List of line numbers.
+#else
+       // REMOVEME
+       DumpList* brancheslabel;
+       DumpList* linenumbers;
+#endif
+
+       methodinfo     *method;
+
+       s4              stackframesize;    /* stackframe size of this method      */
+
+#if defined(ENABLE_REPLACEMENT)
+       rplpoint       *replacementpoint;  /* current replacement point           */
+#endif
+};
+
+
+#define CODEGENDATA_FLAG_ERROR           0x00000001
+#define CODEGENDATA_FLAG_LONGBRANCHES    0x00000002
+
+
+#define CODEGENDATA_HAS_FLAG_ERROR(cd) \
+    ((cd)->flags & CODEGENDATA_FLAG_ERROR)
+
+#define CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd) \
+    ((cd)->flags & CODEGENDATA_FLAG_LONGBRANCHES)
+
+
+/* branchref *****************************************************************/
+
+struct branchref {
+       s4         branchmpc;       /* patching position in code segment          */
+       s4         condition;       /* conditional branch condition               */
+       s4         reg;             /* register number to check                   */
+       u4         options;         /* branch options                             */
+       branchref *next;            /* next element in branchref list             */
+};
+
+
+/* branch_label_ref_t *********************************************************/
+
+struct branch_label_ref_t {
+       s4         mpc;             /* position in code segment                   */
+       s4         label;           /* label number                               */
+       s4         condition;       /* conditional branch condition               */
+       s4         reg;             /* register number to check                   */
+       u4         options;         /* branch options                             */
+/*     listnode_t linkage; */
+};
+
+
+/* jumpref ********************************************************************/
+
+struct jumpref {
+       s4          tablepos;       /* patching position in data segment          */
+       basicblock *target;         /* target basic block                         */
+       jumpref    *next;           /* next element in jumpref list               */
+};
+
+
+/* dataref ********************************************************************/
+
+struct dataref {
+       s4       datapos;           /* patching position in generated code        */
+       dataref *next;              /* next element in dataref list               */
+};
+
+
+/* function prototypes ********************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void codegen_init(void);
+void codegen_setup(jitdata *jd);
+
+bool codegen_generate(jitdata *jd);
+bool codegen_emit(jitdata *jd);
+
+#if defined(ENABLE_INTRP)
+bool intrp_codegen(jitdata *jd);
+#endif
+
+void codegen_close(void);
+
+void codegen_increase(codegendata *cd);
+
+#if defined(ENABLE_INTRP)
+u1 *codegen_ncode_increase(codegendata *cd, u1 *ncodeptr);
+#endif
+
+void codegen_add_branch_ref(codegendata *cd, basicblock *target, s4 condition, s4 reg, u4 options);
+void codegen_resolve_branchrefs(codegendata *cd, basicblock *bptr);
+
+void codegen_branch_label_add(codegendata *cd, s4 label, s4 condition, s4 reg, u4 options);
+
+#if defined(ENABLE_REPLACEMENT)
+#if !defined(NDEBUG)
+void codegen_set_replacement_point_notrap(codegendata *cd, s4 type);
+void codegen_set_replacement_point(codegendata *cd, s4 type);
+#else
+void codegen_set_replacement_point_notrap(codegendata *cd);
+void codegen_set_replacement_point(codegendata *cd);
+#endif
+#endif /* defined(ENABLE_REPLACEMENT) */
+
+void codegen_finish(jitdata *jd);
+
+java_handle_t *codegen_start_native_call(u1 *currentsp, u1 *pv);
+java_object_t *codegen_finish_native_call(u1 *currentsp, u1 *pv);
+
+s4 codegen_reg_of_var(u2 opcode, varinfo *v, s4 tempregnum);
+s4 codegen_reg_of_dst(jitdata *jd, instruction *iptr, s4 tempregnum);
+
+#if defined(ENABLE_SSA)
+void codegen_emit_phi_moves(jitdata *jd, basicblock *bptr);
+#endif
+
+// REMOVEME
+void codegen_emit_stub_compiler(jitdata *jd);
+void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int skipparams);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _CODEGEN_COMMON_HPP
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
index 8e2fdef105191fb46ae6562ce488e0d6adf6e8ef..02eae59e06e2207bea4593e53f873186a017633f 100644 (file)
 #ifndef _DISASS_H
 #define _DISASS_H
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #include "config.h"
 
 #if defined(WITH_BINUTILS_DISASSEMBLER)
@@ -50,9 +46,9 @@ extern "C" {
 #define DISASSINSTR(code) \
     do { \
         if (opt_intrp) \
-            (code) = intrp_disassinstr((code)); \
+            (code) = intrp_disassinstr((u1*) (code));  \
         else \
-            (code) = disassinstr((code)); \
+            (code) = disassinstr((u1*) (code));        \
     } while (0)
 
 #define DISASSEMBLE(start,end) \
@@ -66,7 +62,7 @@ extern "C" {
 # else /* defined(ENABLE_INTRP) */
 
 #define DISASSINSTR(code) \
-    (code) = disassinstr((code))
+    (code) = disassinstr((u1*) (code))
 
 #define DISASSEMBLE(start,end) \
     disassemble((start), (end))
@@ -75,7 +71,7 @@ extern "C" {
 #else /* defined(ENABLE_JIT) */
 
 #define DISASSINSTR(code) \
-    (code) = intrp_disassinstr((code))
+    (code) = intrp_disassinstr((u1*) (code))
 
 #define DISASSEMBLE(start,end) \
     intrp_disassemble((start), (end))
@@ -98,6 +94,10 @@ extern s4   disass_len;
 
 /* function prototypes *******************************************************/
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #if defined(ENABLE_JIT)
 void disassemble(u1 *start, u1 *end);
 #endif
@@ -119,12 +119,12 @@ u1 *intrp_disassinstr(u1 *code);
 void intrp_disassemble(u1 *start, u1 *end);
 #endif
 
-#endif /* defined(ENABLE_DISASSEMBLER) */
-
 #ifdef __cplusplus
-}
+} // extern "C"
 #endif
 
+#endif /* defined(ENABLE_DISASSEMBLER) */
+
 #endif // _DISASS_H
 
 
index 5de1e5da21791e7df22439de2126405a80fa509c..b66da4bd4c3ed83bfe60b8ffedcbe78056ab76cc 100644 (file)
@@ -33,7 +33,7 @@
 
 #include "vm/options.h"
 
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/codegen-common.hpp"
 #include "vm/jit/methodheader.h"
 
 
index c69406fc9d870a3841dda8854f039f95b440f3c0..a18a6b135a89861e87836bd335081f4d7b5fe638 100644 (file)
@@ -34,12 +34,10 @@ typedef struct dsegentry dsegentry;
 #include "config.h"
 #include "vm/types.h"
 
-#include "toolbox/list.h"
-
 #include "vm/references.h"
 
-#include "vm/jit/jit.h"
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/codegen-common.hpp"
 
 
 /* convenience macros *********************************************************/
@@ -64,6 +62,10 @@ struct dsegentry {
 
 /* function prototypes ********************************************************/
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 void dseg_finish(jitdata *jd);
 
 s4 dseg_add_unique_s4(codegendata *cd, s4 value);
@@ -90,6 +92,10 @@ void dseg_resolve_datareferences(jitdata *jd);
 void dseg_display(jitdata *jd);
 #endif
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* _DSEG_H */
 
 
diff --git a/src/vm/jit/emit-common.c b/src/vm/jit/emit-common.c
deleted file mode 100644 (file)
index 22422e2..0000000
+++ /dev/null
@@ -1,731 +0,0 @@
-/* src/vm/jit/emit-common.c - common code emitter functions
-
-   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 "vm/types.h"
-
-#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"
-
-
-/* emit_load_s1 ****************************************************************
-
-   Emits a possible load of the first source operand.
-
-*******************************************************************************/
-
-s4 emit_load_s1(jitdata *jd, instruction *iptr, s4 tempreg)
-{
-       varinfo *src;
-       s4       reg;
-
-       src = VAROP(iptr->s1);
-
-       reg = emit_load(jd, iptr, src, tempreg);
-
-       return reg;
-}
-
-
-/* emit_load_s2 ****************************************************************
-
-   Emits a possible load of the second source operand.
-
-*******************************************************************************/
-
-s4 emit_load_s2(jitdata *jd, instruction *iptr, s4 tempreg)
-{
-       varinfo *src;
-       s4       reg;
-
-       src = VAROP(iptr->sx.s23.s2);
-
-       reg = emit_load(jd, iptr, src, tempreg);
-
-       return reg;
-}
-
-
-/* emit_load_s3 ****************************************************************
-
-   Emits a possible load of the third source operand.
-
-*******************************************************************************/
-
-s4 emit_load_s3(jitdata *jd, instruction *iptr, s4 tempreg)
-{
-       varinfo *src;
-       s4       reg;
-
-       src = VAROP(iptr->sx.s23.s3);
-
-       reg = emit_load(jd, iptr, src, tempreg);
-
-       return reg;
-}
-
-
-/* emit_load_s1_low ************************************************************
-
-   Emits a possible load of the low 32-bits of the first long source
-   operand.
-
-*******************************************************************************/
-
-#if SIZEOF_VOID_P == 4
-s4 emit_load_s1_low(jitdata *jd, instruction *iptr, s4 tempreg)
-{
-       varinfo *src;
-       s4       reg;
-
-       src = VAROP(iptr->s1);
-
-       reg = emit_load_low(jd, iptr, src, tempreg);
-
-       return reg;
-}
-#endif
-
-
-/* emit_load_s2_low ************************************************************
-
-   Emits a possible load of the low 32-bits of the second long source
-   operand.
-
-*******************************************************************************/
-
-#if SIZEOF_VOID_P == 4
-s4 emit_load_s2_low(jitdata *jd, instruction *iptr, s4 tempreg)
-{
-       varinfo *src;
-       s4       reg;
-
-       src = VAROP(iptr->sx.s23.s2);
-
-       reg = emit_load_low(jd, iptr, src, tempreg);
-
-       return reg;
-}
-#endif
-
-
-/* emit_load_s3_low ************************************************************
-
-   Emits a possible load of the low 32-bits of the third long source
-   operand.
-
-*******************************************************************************/
-
-#if SIZEOF_VOID_P == 4
-s4 emit_load_s3_low(jitdata *jd, instruction *iptr, s4 tempreg)
-{
-       varinfo *src;
-       s4       reg;
-
-       src = VAROP(iptr->sx.s23.s3);
-
-       reg = emit_load_low(jd, iptr, src, tempreg);
-
-       return reg;
-}
-#endif
-
-
-/* emit_load_s1_high ***********************************************************
-
-   Emits a possible load of the high 32-bits of the first long source
-   operand.
-
-*******************************************************************************/
-
-#if SIZEOF_VOID_P == 4
-s4 emit_load_s1_high(jitdata *jd, instruction *iptr, s4 tempreg)
-{
-       varinfo *src;
-       s4       reg;
-
-       src = VAROP(iptr->s1);
-
-       reg = emit_load_high(jd, iptr, src, tempreg);
-
-       return reg;
-}
-#endif
-
-
-/* emit_load_s2_high ***********************************************************
-
-   Emits a possible load of the high 32-bits of the second long source
-   operand.
-
-*******************************************************************************/
-
-#if SIZEOF_VOID_P == 4
-s4 emit_load_s2_high(jitdata *jd, instruction *iptr, s4 tempreg)
-{
-       varinfo *src;
-       s4       reg;
-
-       src = VAROP(iptr->sx.s23.s2);
-
-       reg = emit_load_high(jd, iptr, src, tempreg);
-
-       return reg;
-}
-#endif
-
-
-/* emit_load_s3_high ***********************************************************
-
-   Emits a possible load of the high 32-bits of the third long source
-   operand.
-
-*******************************************************************************/
-
-#if SIZEOF_VOID_P == 4
-s4 emit_load_s3_high(jitdata *jd, instruction *iptr, s4 tempreg)
-{
-       varinfo *src;
-       s4       reg;
-
-       src = VAROP(iptr->sx.s23.s3);
-
-       reg = emit_load_high(jd, iptr, src, tempreg);
-
-       return reg;
-}
-#endif
-
-
-/* emit_store_dst **************************************************************
-
-   This function generates the code to store the result of an
-   operation back into a spilled pseudo-variable.  If the
-   pseudo-variable has not been spilled in the first place, this
-   function will generate nothing.
-    
-*******************************************************************************/
-
-void emit_store_dst(jitdata *jd, instruction *iptr, s4 d)
-{
-       emit_store(jd, iptr, VAROP(iptr->dst), d);
-}
-
-
-/* emit_patcher_traps **********************************************************
-
-   Generates the code for the patcher traps.
-
-*******************************************************************************/
-
-void emit_patcher_traps(jitdata *jd)
-{
-       codegendata *cd;
-       codeinfo    *code;
-       patchref_t  *pr;
-       u1          *savedmcodeptr;
-       u1          *tmpmcodeptr;
-       uint32_t     mcode;
-
-       /* get required compiler data */
-
-       cd   = jd->cd;
-       code = jd->code;
-
-       /* generate patcher traps code */
-
-       for (pr = list_first(code->patchers); pr != NULL; pr = list_next(code->patchers, pr)) {
-
-               /* Calculate the patch position where the original machine
-                  code is located and the trap should be placed. */
-
-               tmpmcodeptr = (u1 *) (cd->mcodebase + pr->mpc);
-
-               /* Patch in the trap to call the signal handler (done at
-                  compile time). */
-
-               savedmcodeptr = cd->mcodeptr;   /* save current mcodeptr          */
-               cd->mcodeptr  = tmpmcodeptr;    /* set mcodeptr to patch position */
-
-               mcode = emit_trap(cd);
-
-               cd->mcodeptr = savedmcodeptr;   /* restore the current mcodeptr   */
-
-               /* Remember the original machine code which is patched
-                  back in later (done at runtime). */
-
-               pr->mcode = mcode;
-       }
-}
-
-
-/* emit_bccz *******************************************************************
-
-   Emit conditional and unconditional branch instructions on integer
-   regiseters.
-
-*******************************************************************************/
-
-void emit_bccz(codegendata *cd, basicblock *target, s4 condition, s4 reg, u4 options)
-{
-       s4 branchmpc;
-       s4 disp;
-
-       /* Target basic block already has an PC, so we can generate the
-          branch immediately. */
-
-       if ((target->mpc >= 0)) {
-               STATISTICS(count_branches_resolved++);
-
-               /* calculate the mpc of the branch instruction */
-
-               branchmpc = cd->mcodeptr - cd->mcodebase;
-               disp      = target->mpc - branchmpc;
-
-#if defined(ENABLE_STATISTICS)
-               count_emit_branch++;
-               if ((int8_t)disp == disp)  count_emit_branch_8bit++; 
-               else if ((int16_t)disp == disp) count_emit_branch_16bit++;
-               else if ((int32_t)disp == disp) count_emit_branch_32bit++;
-# if SIZEOF_VOID_P == 8
-               else if ((int64_t)disp == disp) count_emit_branch_64bit++;
-# endif
-#endif
-
-               emit_branch(cd, disp, condition, reg, options);
-       }
-       else {
-               /* current mcodeptr is the correct position,
-                  afterwards emit the NOPs */
-
-               codegen_add_branch_ref(cd, target, condition, reg, options);
-
-               /* generate NOPs as placeholder for branch code */
-
-               BRANCH_NOPS;
-       }
-}
-
-
-/* emit_bcc ********************************************************************
-
-   Emit conditional and unconditional branch instructions on condition
-   codes.
-
-*******************************************************************************/
-
-void emit_bcc(codegendata *cd, basicblock *target, s4 condition, u4 options)
-{
-       emit_bccz(cd, target, condition, -1, options);
-}
-
-
-/* emit_br *********************************************************************
-
-   Wrapper for unconditional branches.
-
-*******************************************************************************/
-
-void emit_br(codegendata *cd, basicblock *target)
-{
-       emit_bcc(cd, target, BRANCH_UNCONDITIONAL, BRANCH_OPT_NONE);
-}
-
-
-/* emit_bxxz *******************************************************************
-
-   Wrappers for branches on one integer register.
-
-*******************************************************************************/
-
-#if SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER
-
-void emit_beqz(codegendata *cd, basicblock *target, s4 reg)
-{
-       emit_bccz(cd, target, BRANCH_EQ, reg, BRANCH_OPT_NONE);
-}
-
-void emit_bnez(codegendata *cd, basicblock *target, s4 reg)
-{
-       emit_bccz(cd, target, BRANCH_NE, reg, BRANCH_OPT_NONE);
-}
-
-void emit_bltz(codegendata *cd, basicblock *target, s4 reg)
-{
-       emit_bccz(cd, target, BRANCH_LT, reg, BRANCH_OPT_NONE);
-}
-
-void emit_bgez(codegendata *cd, basicblock *target, s4 reg)
-{
-       emit_bccz(cd, target, BRANCH_GE, reg, BRANCH_OPT_NONE);
-}
-
-void emit_bgtz(codegendata *cd, basicblock *target, s4 reg)
-{
-       emit_bccz(cd, target, BRANCH_GT, reg, BRANCH_OPT_NONE);
-}
-
-void emit_blez(codegendata *cd, basicblock *target, s4 reg)
-{
-       emit_bccz(cd, target, BRANCH_LE, reg, BRANCH_OPT_NONE);
-}
-
-#endif /* SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER */
-
-
-/* emit_bxx ********************************************************************
-
-   Wrappers for branches on two integer registers.
-
-   We use PACK_REGS here, so we don't have to change the branchref
-   data structure and the emit_bccz function.
-
-*******************************************************************************/
-
-#if SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS
-
-void emit_beq(codegendata *cd, basicblock *target, s4 s1, s4 s2)
-{
-       emit_bccz(cd, target, BRANCH_EQ, PACK_REGS(s1, s2), BRANCH_OPT_NONE);
-}
-
-void emit_bne(codegendata *cd, basicblock *target, s4 s1, s4 s2)
-{
-       emit_bccz(cd, target, BRANCH_NE, PACK_REGS(s1, s2), BRANCH_OPT_NONE);
-}
-
-#endif /* SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS */
-
-
-/* emit_bxx ********************************************************************
-
-   Wrappers for branches on condition codes.
-
-*******************************************************************************/
-
-#if SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER
-
-void emit_beq(codegendata *cd, basicblock *target)
-{
-       emit_bcc(cd, target, BRANCH_EQ, BRANCH_OPT_NONE);
-}
-
-void emit_bne(codegendata *cd, basicblock *target)
-{
-       emit_bcc(cd, target, BRANCH_NE, BRANCH_OPT_NONE);
-}
-
-void emit_blt(codegendata *cd, basicblock *target)
-{
-       emit_bcc(cd, target, BRANCH_LT, BRANCH_OPT_NONE);
-}
-
-void emit_bge(codegendata *cd, basicblock *target)
-{
-       emit_bcc(cd, target, BRANCH_GE, BRANCH_OPT_NONE);
-}
-
-void emit_bgt(codegendata *cd, basicblock *target)
-{
-       emit_bcc(cd, target, BRANCH_GT, BRANCH_OPT_NONE);
-}
-
-void emit_ble(codegendata *cd, basicblock *target)
-{
-       emit_bcc(cd, target, BRANCH_LE, BRANCH_OPT_NONE);
-}
-
-#if SUPPORT_BRANCH_CONDITIONAL_UNSIGNED_CONDITIONS
-void emit_bult(codegendata *cd, basicblock *target)
-{
-       emit_bcc(cd, target, BRANCH_ULT, BRANCH_OPT_NONE);
-}
-
-void emit_bule(codegendata *cd, basicblock *target)
-{
-       emit_bcc(cd, target, BRANCH_ULE, BRANCH_OPT_NONE);
-}
-
-void emit_buge(codegendata *cd, basicblock *target)
-{
-       emit_bcc(cd, target, BRANCH_UGE, BRANCH_OPT_NONE);
-}
-
-void emit_bugt(codegendata *cd, basicblock *target)
-{
-       emit_bcc(cd, target, BRANCH_UGT, BRANCH_OPT_NONE);
-}
-#endif
-
-#if defined(__POWERPC__) || defined(__POWERPC64__)
-void emit_bnan(codegendata *cd, basicblock *target)
-{
-       emit_bcc(cd, target, BRANCH_NAN, BRANCH_OPT_NONE);
-}
-#endif
-
-#endif /* SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER */
-
-
-/* emit_label_bccz *************************************************************
-
-   Emit a branch to a label.  Possibly emit the branch, if it is a
-   backward branch.
-
-*******************************************************************************/
-
-void emit_label_bccz(codegendata *cd, s4 label, s4 condition, s4 reg, u4 options)
-{
-       list_t             *list;
-       branch_label_ref_t *br;
-       s4                  mpc;
-       s4                  disp;
-
-       /* get the label list */
-
-       list = cd->brancheslabel;
-
-       /* search if the label is already in the list */
-
-       for (br = list_first(list); br != NULL; br = list_next(list, br)) {
-               /* is this entry the correct label? */
-
-               if (br->label == label)
-                       break;
-       }
-
-       if (br == NULL) {
-               /* current mcodeptr is the correct position,
-                  afterwards emit the NOPs */
-
-               codegen_branch_label_add(cd, label, condition, reg, options);
-
-               /* generate NOPs as placeholder for branch code */
-
-               BRANCH_NOPS;
-               return;
-       }
-
-       /* Branch reference was found. */
-
-       /* calculate the mpc of the branch instruction */
-
-       mpc  = cd->mcodeptr - cd->mcodebase;
-       disp = br->mpc - mpc;
-
-#if defined(ENABLE_STATISTICS)
-       count_emit_branch++;
-       if ((int8_t)disp == disp)  count_emit_branch_8bit++; 
-       else if ((int16_t)disp == disp) count_emit_branch_16bit++;
-       else if ((int32_t)disp == disp) count_emit_branch_32bit++;
-# if SIZEOF_VOID_P == 8
-       else if ((int64_t)disp == disp) count_emit_branch_64bit++;
-# endif
-#endif
-
-       emit_branch(cd, disp, condition, reg, options);
-
-       /* now remove the branch reference */
-
-       list_remove(list, br);
-}
-
-
-/* emit_label ******************************************************************
-
-   Emit a label for a branch.  Possibly emit the branch, if it is a
-   forward branch.
-
-*******************************************************************************/
-
-void emit_label(codegendata *cd, s4 label)
-{
-       list_t             *list;
-       branch_label_ref_t *br;
-       s4                  mpc;
-       s4                  disp;
-       u1                 *mcodeptr;
-
-       /* get the label list */
-
-       list = cd->brancheslabel;
-
-       /* search if the label is already in the list */
-
-       for (br = list_first(list); br != NULL; br = list_next(list, br)) {
-               /* is this entry the correct label? */
-
-               if (br->label == label)
-                       break;
-       }
-
-       if (br == NULL) {
-               /* No branch reference found, add the label to the list (use
-                  invalid values for condition and register). */
-
-               codegen_branch_label_add(cd, label, -1, -1, BRANCH_OPT_NONE );
-               return;
-       }
-
-       /* Branch reference was found. */
-
-       /* calculate the mpc of the branch instruction */
-
-       mpc  = cd->mcodeptr - cd->mcodebase;
-       disp = mpc - br->mpc;
-
-       /* temporary set the mcodeptr */
-
-       mcodeptr     = cd->mcodeptr;
-       cd->mcodeptr = cd->mcodebase + br->mpc;
-
-#if defined(ENABLE_STATISTICS)
-       count_emit_branch++;
-       if ((int8_t)disp == disp)  count_emit_branch_8bit++; 
-       else if ((int16_t)disp == disp) count_emit_branch_16bit++;
-       else if ((int32_t)disp == disp) count_emit_branch_32bit++;
-# if SIZEOF_VOID_P == 8
-       else if ((int64_t)disp == disp) count_emit_branch_64bit++;
-# endif
-#endif
-
-       emit_branch(cd, disp, br->condition, br->reg, br->options);
-
-       /* restore mcodeptr */
-
-       cd->mcodeptr = mcodeptr;
-
-       /* now remove the branch reference */
-
-       list_remove(list, br);
-}
-
-
-/* emit_label_bcc **************************************************************
-
-   Emit conditional and unconditional label-branch instructions on
-   condition codes.
-
-*******************************************************************************/
-
-void emit_label_bcc(codegendata *cd, s4 label, s4 condition, u4 options)
-{
-       emit_label_bccz(cd, label, condition, -1, options);
-}
-
-
-/* emit_label_br ***************************************************************
-
-   Wrapper for unconditional label-branches.
-
-*******************************************************************************/
-
-void emit_label_br(codegendata *cd, s4 label)
-{
-       emit_label_bcc(cd, label, BRANCH_UNCONDITIONAL, BRANCH_OPT_NONE);
-}
-
-
-/* emit_label_bxxz *************************************************************
-
-   Wrappers for label-branches on one integer register.
-
-*******************************************************************************/
-
-#if SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER
-
-void emit_label_beqz(codegendata *cd, s4 label, s4 reg)
-{
-       emit_label_bccz(cd, label, BRANCH_EQ, reg, BRANCH_OPT_NONE);
-}
-
-#endif /* SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER */
-
-
-/* emit_label_bxx **************************************************************
-
-   Wrappers for label-branches on condition codes.
-
-*******************************************************************************/
-
-#if SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER
-
-void emit_label_beq(codegendata *cd, s4 label)
-{
-       emit_label_bcc(cd, label, BRANCH_EQ, BRANCH_OPT_NONE);
-}
-
-void emit_label_bne(codegendata *cd, s4 label)
-{
-       emit_label_bcc(cd, label, BRANCH_NE, BRANCH_OPT_NONE);
-}
-
-void emit_label_blt(codegendata *cd, s4 label)
-{
-       emit_label_bcc(cd, label, BRANCH_LT, BRANCH_OPT_NONE);
-}
-
-void emit_label_bge(codegendata *cd, s4 label)
-{
-       emit_label_bcc(cd, label, BRANCH_GE, BRANCH_OPT_NONE);
-}
-
-void emit_label_bgt(codegendata *cd, s4 label)
-{
-       emit_label_bcc(cd, label, BRANCH_GT, BRANCH_OPT_NONE);
-}
-
-void emit_label_ble(codegendata *cd, s4 label)
-{
-       emit_label_bcc(cd, label, BRANCH_LE, BRANCH_OPT_NONE);
-}
-
-#endif /* SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER */
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
diff --git a/src/vm/jit/emit-common.cpp b/src/vm/jit/emit-common.cpp
new file mode 100644 (file)
index 0000000..04bdcbb
--- /dev/null
@@ -0,0 +1,720 @@
+/* src/vm/jit/emit-common.cpp - common code emitter functions
+
+   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 <algorithm>
+
+#include "vm/types.h"
+
+#include "arch.h"
+#include "codegen.h"
+
+#include "toolbox/list.hpp"
+
+#include "vm/options.h"
+#include "vm/statistics.h"
+
+#include "vm/jit/emit-common.hpp"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/patcher-common.hpp"
+
+
+/* emit_load_s1 ****************************************************************
+
+   Emits a possible load of the first source operand.
+
+*******************************************************************************/
+
+s4 emit_load_s1(jitdata *jd, instruction *iptr, s4 tempreg)
+{
+       varinfo *src;
+       s4       reg;
+
+       src = VAROP(iptr->s1);
+
+       reg = emit_load(jd, iptr, src, tempreg);
+
+       return reg;
+}
+
+
+/* emit_load_s2 ****************************************************************
+
+   Emits a possible load of the second source operand.
+
+*******************************************************************************/
+
+s4 emit_load_s2(jitdata *jd, instruction *iptr, s4 tempreg)
+{
+       varinfo *src;
+       s4       reg;
+
+       src = VAROP(iptr->sx.s23.s2);
+
+       reg = emit_load(jd, iptr, src, tempreg);
+
+       return reg;
+}
+
+
+/* emit_load_s3 ****************************************************************
+
+   Emits a possible load of the third source operand.
+
+*******************************************************************************/
+
+s4 emit_load_s3(jitdata *jd, instruction *iptr, s4 tempreg)
+{
+       varinfo *src;
+       s4       reg;
+
+       src = VAROP(iptr->sx.s23.s3);
+
+       reg = emit_load(jd, iptr, src, tempreg);
+
+       return reg;
+}
+
+
+/* emit_load_s1_low ************************************************************
+
+   Emits a possible load of the low 32-bits of the first long source
+   operand.
+
+*******************************************************************************/
+
+#if SIZEOF_VOID_P == 4
+s4 emit_load_s1_low(jitdata *jd, instruction *iptr, s4 tempreg)
+{
+       varinfo *src;
+       s4       reg;
+
+       src = VAROP(iptr->s1);
+
+       reg = emit_load_low(jd, iptr, src, tempreg);
+
+       return reg;
+}
+#endif
+
+
+/* emit_load_s2_low ************************************************************
+
+   Emits a possible load of the low 32-bits of the second long source
+   operand.
+
+*******************************************************************************/
+
+#if SIZEOF_VOID_P == 4
+s4 emit_load_s2_low(jitdata *jd, instruction *iptr, s4 tempreg)
+{
+       varinfo *src;
+       s4       reg;
+
+       src = VAROP(iptr->sx.s23.s2);
+
+       reg = emit_load_low(jd, iptr, src, tempreg);
+
+       return reg;
+}
+#endif
+
+
+/* emit_load_s3_low ************************************************************
+
+   Emits a possible load of the low 32-bits of the third long source
+   operand.
+
+*******************************************************************************/
+
+#if SIZEOF_VOID_P == 4
+s4 emit_load_s3_low(jitdata *jd, instruction *iptr, s4 tempreg)
+{
+       varinfo *src;
+       s4       reg;
+
+       src = VAROP(iptr->sx.s23.s3);
+
+       reg = emit_load_low(jd, iptr, src, tempreg);
+
+       return reg;
+}
+#endif
+
+
+/* emit_load_s1_high ***********************************************************
+
+   Emits a possible load of the high 32-bits of the first long source
+   operand.
+
+*******************************************************************************/
+
+#if SIZEOF_VOID_P == 4
+s4 emit_load_s1_high(jitdata *jd, instruction *iptr, s4 tempreg)
+{
+       varinfo *src;
+       s4       reg;
+
+       src = VAROP(iptr->s1);
+
+       reg = emit_load_high(jd, iptr, src, tempreg);
+
+       return reg;
+}
+#endif
+
+
+/* emit_load_s2_high ***********************************************************
+
+   Emits a possible load of the high 32-bits of the second long source
+   operand.
+
+*******************************************************************************/
+
+#if SIZEOF_VOID_P == 4
+s4 emit_load_s2_high(jitdata *jd, instruction *iptr, s4 tempreg)
+{
+       varinfo *src;
+       s4       reg;
+
+       src = VAROP(iptr->sx.s23.s2);
+
+       reg = emit_load_high(jd, iptr, src, tempreg);
+
+       return reg;
+}
+#endif
+
+
+/* emit_load_s3_high ***********************************************************
+
+   Emits a possible load of the high 32-bits of the third long source
+   operand.
+
+*******************************************************************************/
+
+#if SIZEOF_VOID_P == 4
+s4 emit_load_s3_high(jitdata *jd, instruction *iptr, s4 tempreg)
+{
+       varinfo *src;
+       s4       reg;
+
+       src = VAROP(iptr->sx.s23.s3);
+
+       reg = emit_load_high(jd, iptr, src, tempreg);
+
+       return reg;
+}
+#endif
+
+
+/* emit_store_dst **************************************************************
+
+   This function generates the code to store the result of an
+   operation back into a spilled pseudo-variable.  If the
+   pseudo-variable has not been spilled in the first place, this
+   function will generate nothing.
+    
+*******************************************************************************/
+
+void emit_store_dst(jitdata *jd, instruction *iptr, s4 d)
+{
+       emit_store(jd, iptr, VAROP(iptr->dst), d);
+}
+
+
+/* emit_patcher_traps **********************************************************
+
+   Generates the code for the patcher traps.
+
+*******************************************************************************/
+
+void emit_patcher_traps(jitdata *jd)
+{
+       codegendata *cd;
+       codeinfo    *code;
+       u1          *savedmcodeptr;
+       u1          *tmpmcodeptr;
+       uint32_t     mcode;
+
+       /* get required compiler data */
+
+       cd   = jd->cd;
+       code = jd->code;
+
+       // Generate patcher traps code.
+       for (List<patchref_t>::iterator it = code->patchers->begin(); it != code->patchers->end(); it++) {
+               patchref_t& pr = *it;
+
+               /* Calculate the patch position where the original machine
+                  code is located and the trap should be placed. */
+
+               tmpmcodeptr = (u1 *) (cd->mcodebase + pr.mpc);
+
+               /* Patch in the trap to call the signal handler (done at
+                  compile time). */
+
+               savedmcodeptr = cd->mcodeptr;   /* save current mcodeptr          */
+               cd->mcodeptr  = tmpmcodeptr;    /* set mcodeptr to patch position */
+
+               mcode = emit_trap(cd);
+
+               cd->mcodeptr = savedmcodeptr;   /* restore the current mcodeptr   */
+
+               /* Remember the original machine code which is patched
+                  back in later (done at runtime). */
+
+               pr.mcode = mcode;
+       }
+}
+
+
+/* emit_bccz *******************************************************************
+
+   Emit conditional and unconditional branch instructions on integer
+   regiseters.
+
+*******************************************************************************/
+
+void emit_bccz(codegendata *cd, basicblock *target, s4 condition, s4 reg, u4 options)
+{
+       s4 branchmpc;
+       s4 disp;
+
+       /* Target basic block already has an PC, so we can generate the
+          branch immediately. */
+
+       if ((target->mpc >= 0)) {
+               STATISTICS(count_branches_resolved++);
+
+               /* calculate the mpc of the branch instruction */
+
+               branchmpc = cd->mcodeptr - cd->mcodebase;
+               disp      = target->mpc - branchmpc;
+
+#if defined(ENABLE_STATISTICS)
+               count_emit_branch++;
+               if ((int8_t)disp == disp)  count_emit_branch_8bit++; 
+               else if ((int16_t)disp == disp) count_emit_branch_16bit++;
+               else if ((int32_t)disp == disp) count_emit_branch_32bit++;
+# if SIZEOF_VOID_P == 8
+               else if ((int64_t)disp == disp) count_emit_branch_64bit++;
+# endif
+#endif
+
+               emit_branch(cd, disp, condition, reg, options);
+       }
+       else {
+               /* current mcodeptr is the correct position,
+                  afterwards emit the NOPs */
+
+               codegen_add_branch_ref(cd, target, condition, reg, options);
+
+               /* generate NOPs as placeholder for branch code */
+
+               BRANCH_NOPS;
+       }
+}
+
+
+/* emit_bcc ********************************************************************
+
+   Emit conditional and unconditional branch instructions on condition
+   codes.
+
+*******************************************************************************/
+
+void emit_bcc(codegendata *cd, basicblock *target, s4 condition, u4 options)
+{
+       emit_bccz(cd, target, condition, -1, options);
+}
+
+
+/* emit_br *********************************************************************
+
+   Wrapper for unconditional branches.
+
+*******************************************************************************/
+
+void emit_br(codegendata *cd, basicblock *target)
+{
+       emit_bcc(cd, target, BRANCH_UNCONDITIONAL, BRANCH_OPT_NONE);
+}
+
+
+/* emit_bxxz *******************************************************************
+
+   Wrappers for branches on one integer register.
+
+*******************************************************************************/
+
+#if SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER
+
+void emit_beqz(codegendata *cd, basicblock *target, s4 reg)
+{
+       emit_bccz(cd, target, BRANCH_EQ, reg, BRANCH_OPT_NONE);
+}
+
+void emit_bnez(codegendata *cd, basicblock *target, s4 reg)
+{
+       emit_bccz(cd, target, BRANCH_NE, reg, BRANCH_OPT_NONE);
+}
+
+void emit_bltz(codegendata *cd, basicblock *target, s4 reg)
+{
+       emit_bccz(cd, target, BRANCH_LT, reg, BRANCH_OPT_NONE);
+}
+
+void emit_bgez(codegendata *cd, basicblock *target, s4 reg)
+{
+       emit_bccz(cd, target, BRANCH_GE, reg, BRANCH_OPT_NONE);
+}
+
+void emit_bgtz(codegendata *cd, basicblock *target, s4 reg)
+{
+       emit_bccz(cd, target, BRANCH_GT, reg, BRANCH_OPT_NONE);
+}
+
+void emit_blez(codegendata *cd, basicblock *target, s4 reg)
+{
+       emit_bccz(cd, target, BRANCH_LE, reg, BRANCH_OPT_NONE);
+}
+
+#endif /* SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER */
+
+
+/* emit_bxx ********************************************************************
+
+   Wrappers for branches on two integer registers.
+
+   We use PACK_REGS here, so we don't have to change the branchref
+   data structure and the emit_bccz function.
+
+*******************************************************************************/
+
+#if SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS
+
+void emit_beq(codegendata *cd, basicblock *target, s4 s1, s4 s2)
+{
+       emit_bccz(cd, target, BRANCH_EQ, PACK_REGS(s1, s2), BRANCH_OPT_NONE);
+}
+
+void emit_bne(codegendata *cd, basicblock *target, s4 s1, s4 s2)
+{
+       emit_bccz(cd, target, BRANCH_NE, PACK_REGS(s1, s2), BRANCH_OPT_NONE);
+}
+
+#endif /* SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS */
+
+
+/* emit_bxx ********************************************************************
+
+   Wrappers for branches on condition codes.
+
+*******************************************************************************/
+
+#if SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER
+
+void emit_beq(codegendata *cd, basicblock *target)
+{
+       emit_bcc(cd, target, BRANCH_EQ, BRANCH_OPT_NONE);
+}
+
+void emit_bne(codegendata *cd, basicblock *target)
+{
+       emit_bcc(cd, target, BRANCH_NE, BRANCH_OPT_NONE);
+}
+
+void emit_blt(codegendata *cd, basicblock *target)
+{
+       emit_bcc(cd, target, BRANCH_LT, BRANCH_OPT_NONE);
+}
+
+void emit_bge(codegendata *cd, basicblock *target)
+{
+       emit_bcc(cd, target, BRANCH_GE, BRANCH_OPT_NONE);
+}
+
+void emit_bgt(codegendata *cd, basicblock *target)
+{
+       emit_bcc(cd, target, BRANCH_GT, BRANCH_OPT_NONE);
+}
+
+void emit_ble(codegendata *cd, basicblock *target)
+{
+       emit_bcc(cd, target, BRANCH_LE, BRANCH_OPT_NONE);
+}
+
+#if SUPPORT_BRANCH_CONDITIONAL_UNSIGNED_CONDITIONS
+void emit_bult(codegendata *cd, basicblock *target)
+{
+       emit_bcc(cd, target, BRANCH_ULT, BRANCH_OPT_NONE);
+}
+
+void emit_bule(codegendata *cd, basicblock *target)
+{
+       emit_bcc(cd, target, BRANCH_ULE, BRANCH_OPT_NONE);
+}
+
+void emit_buge(codegendata *cd, basicblock *target)
+{
+       emit_bcc(cd, target, BRANCH_UGE, BRANCH_OPT_NONE);
+}
+
+void emit_bugt(codegendata *cd, basicblock *target)
+{
+       emit_bcc(cd, target, BRANCH_UGT, BRANCH_OPT_NONE);
+}
+#endif
+
+#if defined(__POWERPC__) || defined(__POWERPC64__)
+void emit_bnan(codegendata *cd, basicblock *target)
+{
+       emit_bcc(cd, target, BRANCH_NAN, BRANCH_OPT_NONE);
+}
+#endif
+
+#endif /* SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER */
+
+
+/* emit_label_bccz *************************************************************
+
+   Emit a branch to a label.  Possibly emit the branch, if it is a
+   backward branch.
+
+*******************************************************************************/
+
+void emit_label_bccz(codegendata *cd, s4 label, s4 condition, s4 reg, u4 options)
+{
+       // Search if the label is already in the list.
+       DumpList<branch_label_ref_t*>::iterator it;
+       for (it = cd->brancheslabel->begin(); it != cd->brancheslabel->end(); it++) {
+               branch_label_ref_t* br = *it;
+
+               /* is this entry the correct label? */
+
+               if (br->label == label)
+                       break;
+       }
+
+       if (it == cd->brancheslabel->end()) {
+               /* current mcodeptr is the correct position,
+                  afterwards emit the NOPs */
+
+               codegen_branch_label_add(cd, label, condition, reg, options);
+
+               /* generate NOPs as placeholder for branch code */
+
+               BRANCH_NOPS;
+               return;
+       }
+
+       // Branch reference was found.
+       branch_label_ref_t* br = *it;
+
+       /* calculate the mpc of the branch instruction */
+
+       int32_t mpc  = cd->mcodeptr - cd->mcodebase;
+       int32_t disp = br->mpc - mpc;
+
+#if defined(ENABLE_STATISTICS)
+       count_emit_branch++;
+       if ((int8_t)disp == disp)  count_emit_branch_8bit++; 
+       else if ((int16_t)disp == disp) count_emit_branch_16bit++;
+       else if ((int32_t)disp == disp) count_emit_branch_32bit++;
+# if SIZEOF_VOID_P == 8
+       else if ((int64_t)disp == disp) count_emit_branch_64bit++;
+# endif
+#endif
+
+       emit_branch(cd, disp, condition, reg, options);
+
+       // Now remove the branch reference.
+       cd->brancheslabel->remove(br);
+}
+
+
+/* emit_label ******************************************************************
+
+   Emit a label for a branch.  Possibly emit the branch, if it is a
+   forward branch.
+
+*******************************************************************************/
+
+void emit_label(codegendata *cd, s4 label)
+{
+       u1* mcodeptr;
+
+       // Search if the label is already in the list.
+       DumpList<branch_label_ref_t*>::iterator it;
+       for (it = cd->brancheslabel->begin(); it != cd->brancheslabel->end(); it++) {
+               branch_label_ref_t* br = *it;
+
+               /* is this entry the correct label? */
+
+               if (br->label == label)
+                       break;
+       }
+
+       if (it == cd->brancheslabel->end()) {
+               /* No branch reference found, add the label to the list (use
+                  invalid values for condition and register). */
+
+               codegen_branch_label_add(cd, label, -1, -1, BRANCH_OPT_NONE );
+               return;
+       }
+
+       // Branch reference was found.
+       branch_label_ref_t* br = *it;
+
+       // Calculate the mpc of the branch instruction.
+       int32_t mpc  = cd->mcodeptr - cd->mcodebase;
+       int32_t disp = mpc - br->mpc;
+
+       /* temporary set the mcodeptr */
+
+       mcodeptr     = cd->mcodeptr;
+       cd->mcodeptr = cd->mcodebase + br->mpc;
+
+#if defined(ENABLE_STATISTICS)
+       count_emit_branch++;
+       if ((int8_t)disp == disp)  count_emit_branch_8bit++; 
+       else if ((int16_t)disp == disp) count_emit_branch_16bit++;
+       else if ((int32_t)disp == disp) count_emit_branch_32bit++;
+# if SIZEOF_VOID_P == 8
+       else if ((int64_t)disp == disp) count_emit_branch_64bit++;
+# endif
+#endif
+
+       emit_branch(cd, disp, br->condition, br->reg, br->options);
+
+       /* restore mcodeptr */
+
+       cd->mcodeptr = mcodeptr;
+
+       // Now remove the branch reference.
+       cd->brancheslabel->remove(br);
+}
+
+
+/* emit_label_bcc **************************************************************
+
+   Emit conditional and unconditional label-branch instructions on
+   condition codes.
+
+*******************************************************************************/
+
+void emit_label_bcc(codegendata *cd, s4 label, s4 condition, u4 options)
+{
+       emit_label_bccz(cd, label, condition, -1, options);
+}
+
+
+/* emit_label_br ***************************************************************
+
+   Wrapper for unconditional label-branches.
+
+*******************************************************************************/
+
+void emit_label_br(codegendata *cd, s4 label)
+{
+       emit_label_bcc(cd, label, BRANCH_UNCONDITIONAL, BRANCH_OPT_NONE);
+}
+
+
+/* emit_label_bxxz *************************************************************
+
+   Wrappers for label-branches on one integer register.
+
+*******************************************************************************/
+
+#if SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER
+
+void emit_label_beqz(codegendata *cd, s4 label, s4 reg)
+{
+       emit_label_bccz(cd, label, BRANCH_EQ, reg, BRANCH_OPT_NONE);
+}
+
+#endif /* SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER */
+
+
+/* emit_label_bxx **************************************************************
+
+   Wrappers for label-branches on condition codes.
+
+*******************************************************************************/
+
+#if SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER
+
+void emit_label_beq(codegendata *cd, s4 label)
+{
+       emit_label_bcc(cd, label, BRANCH_EQ, BRANCH_OPT_NONE);
+}
+
+void emit_label_bne(codegendata *cd, s4 label)
+{
+       emit_label_bcc(cd, label, BRANCH_NE, BRANCH_OPT_NONE);
+}
+
+void emit_label_blt(codegendata *cd, s4 label)
+{
+       emit_label_bcc(cd, label, BRANCH_LT, BRANCH_OPT_NONE);
+}
+
+void emit_label_bge(codegendata *cd, s4 label)
+{
+       emit_label_bcc(cd, label, BRANCH_GE, BRANCH_OPT_NONE);
+}
+
+void emit_label_bgt(codegendata *cd, s4 label)
+{
+       emit_label_bcc(cd, label, BRANCH_GT, BRANCH_OPT_NONE);
+}
+
+void emit_label_ble(codegendata *cd, s4 label)
+{
+       emit_label_bcc(cd, label, BRANCH_LE, BRANCH_OPT_NONE);
+}
+
+#endif /* SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER */
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
diff --git a/src/vm/jit/emit-common.h b/src/vm/jit/emit-common.h
deleted file mode 100644 (file)
index f0f854a..0000000
+++ /dev/null
@@ -1,204 +0,0 @@
-/* src/vm/jit/emit-common.h - common code emitter functions
-
-   Copyright (C) 2006, 2007 R. Grafl, A. Krall, C. Kruegel, C. Oates,
-   R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
-   C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
-   Institut f. Computersprachen - TU Wien
-
-   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 _EMIT_COMMON_H
-#define _EMIT_COMMON_H
-
-#include "config.h"
-#include "vm/types.h"
-
-#include "arch.h"
-
-#include "vm/jit/codegen-common.h"
-#include "vm/jit/jit.h"
-
-
-/* branch labels **************************************************************/
-
-#define BRANCH_LABEL_1    1
-#define BRANCH_LABEL_2    2
-#define BRANCH_LABEL_3    3
-#define BRANCH_LABEL_4    4
-#define BRANCH_LABEL_5    5
-#define BRANCH_LABEL_6    6
-
-
-/* constant range macros ******************************************************/
-
-#if SIZEOF_VOID_P == 8
-
-# define IS_IMM8(c) \
-    (((s8) (c) >= -128) && ((s8) (c) <= 127))
-
-# define IS_IMM32(c) \
-    (((s8) (c) >= (-2147483647-1)) && ((s8) (c) <= 2147483647))
-
-#else
-
-# define IS_IMM8(c) \
-    (((s4) (c) >= -128) && ((s4) (c) <= 127))
-
-# define IS_IMM16(c) \
-    (((s4) (c) >= -32768) && ((s4) (c) <= 32767))
-
-#endif
-
-
-/* code generation functions **************************************************/
-
-s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg);
-s4 emit_load_s1(jitdata *jd, instruction *iptr, s4 tempreg);
-s4 emit_load_s2(jitdata *jd, instruction *iptr, s4 tempreg);
-s4 emit_load_s3(jitdata *jd, instruction *iptr, s4 tempreg);
-
-#if SIZEOF_VOID_P == 4
-s4 emit_load_low(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg);
-s4 emit_load_s1_low(jitdata *jd, instruction *iptr, s4 tempreg);
-s4 emit_load_s2_low(jitdata *jd, instruction *iptr, s4 tempreg);
-s4 emit_load_s3_low(jitdata *jd, instruction *iptr, s4 tempreg);
-
-s4 emit_load_high(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg);
-s4 emit_load_s1_high(jitdata *jd, instruction *iptr, s4 tempreg);
-s4 emit_load_s2_high(jitdata *jd, instruction *iptr, s4 tempreg);
-s4 emit_load_s3_high(jitdata *jd, instruction *iptr, s4 tempreg);
-#endif
-
-void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d);
-void emit_store_dst(jitdata *jd, instruction *iptr, s4 d);
-
-#if SIZEOF_VOID_P == 4
-void emit_store_low(jitdata *jd, instruction *iptr, varinfo *dst, s4 d);
-void emit_store_high(jitdata *jd, instruction *iptr, varinfo *dst, s4 d);
-#endif
-
-void emit_copy(jitdata *jd, instruction *iptr);
-
-void emit_iconst(codegendata *cd, s4 d, s4 value);
-void emit_lconst(codegendata *cd, s4 d, s8 value);
-
-/* branch-emitting functions */
-void emit_bccz(codegendata *cd, basicblock *target, s4 condition, s4 reg, u4 options);
-void emit_bcc(codegendata *cd, basicblock *target, s4 condition, u4 options);
-
-/* wrapper for unconditional branches */
-void emit_br(codegendata *cd, basicblock *target);
-
-/* wrappers for branches on one integer register */
-
-#if SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER
-void emit_beqz(codegendata *cd, basicblock *target, s4 reg);
-void emit_bnez(codegendata *cd, basicblock *target, s4 reg);
-void emit_bltz(codegendata *cd, basicblock *target, s4 reg);
-void emit_bgez(codegendata *cd, basicblock *target, s4 reg);
-void emit_bgtz(codegendata *cd, basicblock *target, s4 reg);
-void emit_blez(codegendata *cd, basicblock *target, s4 reg);
-#endif
-
-/* wrappers for branches on two integer registers */
-
-#if SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS
-void emit_beq(codegendata *cd, basicblock *target, s4 s1, s4 s2);
-void emit_bne(codegendata *cd, basicblock *target, s4 s1, s4 s2);
-#endif
-
-/* wrappers for branches on condition codes */
-
-#if SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER
-void emit_beq(codegendata *cd, basicblock *target);
-void emit_bne(codegendata *cd, basicblock *target);
-void emit_blt(codegendata *cd, basicblock *target);
-void emit_bge(codegendata *cd, basicblock *target);
-void emit_bgt(codegendata *cd, basicblock *target);
-void emit_ble(codegendata *cd, basicblock *target);
-#endif
-
-#if SUPPORT_BRANCH_CONDITIONAL_UNSIGNED_CONDITIONS
-void emit_bult(codegendata *cd, basicblock *target);
-void emit_bule(codegendata *cd, basicblock *target);
-void emit_buge(codegendata *cd, basicblock *target);
-void emit_bugt(codegendata *cd, basicblock *target);
-#endif
-
-#if defined(__POWERPC__) || defined(__POWERPC64__)
-void emit_bnan(codegendata *cd, basicblock *target);
-#endif
-
-/* label-branches */
-void emit_label_bccz(codegendata *cd, s4 label, s4 condition, s4 reg, u4 options);
-void emit_label(codegendata *cd, s4 label);
-void emit_label_bcc(codegendata *cd, s4 label, s4 condition, u4 options);
-
-void emit_label_br(codegendata *cd, s4 label);
-
-#if SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER
-void emit_label_beqz(codegendata *cd, s4 label, s4 reg);
-#endif
-
-#if SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER
-void emit_label_beq(codegendata *cd, s4 label);
-void emit_label_bne(codegendata *cd, s4 label);
-void emit_label_blt(codegendata *cd, s4 label);
-void emit_label_bge(codegendata *cd, s4 label);
-void emit_label_bgt(codegendata *cd, s4 label);
-void emit_label_ble(codegendata *cd, s4 label);
-#endif
-
-/* machine dependent branch-emitting function */
-void emit_branch(codegendata *cd, s4 disp, s4 condition, s4 reg, u4 options);
-
-void emit_arithmetic_check(codegendata *cd, instruction *iptr, s4 reg);
-void emit_arrayindexoutofbounds_check(codegendata *cd, instruction *iptr, s4 s1, s4 s2);
-void emit_arraystore_check(codegendata *cd, instruction *iptr);
-void emit_classcast_check(codegendata *cd, instruction *iptr, s4 condition, s4 reg, s4 s1);
-void emit_nullpointer_check(codegendata *cd, instruction *iptr, s4 reg);
-void emit_exception_check(codegendata *cd, instruction *iptr);
-
-void emit_trap_compiler(codegendata *cd);
-void emit_trap_countdown(codegendata *cd, s4 *counter);
-uint32_t emit_trap(codegendata *cd);
-
-void emit_patcher_traps(jitdata *jd);
-
-void emit_verbosecall_enter(jitdata *jd);
-void emit_verbosecall_exit(jitdata *jd);
-
-#endif /* _EMIT_COMMON_H */
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
diff --git a/src/vm/jit/emit-common.hpp b/src/vm/jit/emit-common.hpp
new file mode 100644 (file)
index 0000000..880f633
--- /dev/null
@@ -0,0 +1,212 @@
+/* src/vm/jit/emit-common.hpp - common code emitter functions
+
+   Copyright (C) 2006, 2007 R. Grafl, A. Krall, C. Kruegel, C. Oates,
+   R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
+   C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
+   Institut f. Computersprachen - TU Wien
+
+   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 _EMIT_COMMON_H
+#define _EMIT_COMMON_H
+
+#include "config.h"
+#include "vm/types.h"
+
+#include "arch.h"
+
+#include "vm/jit/codegen-common.hpp"
+#include "vm/jit/jit.hpp"
+
+
+/* branch labels **************************************************************/
+
+#define BRANCH_LABEL_1    1
+#define BRANCH_LABEL_2    2
+#define BRANCH_LABEL_3    3
+#define BRANCH_LABEL_4    4
+#define BRANCH_LABEL_5    5
+#define BRANCH_LABEL_6    6
+
+
+/* constant range macros ******************************************************/
+
+#if SIZEOF_VOID_P == 8
+
+# define IS_IMM8(c) \
+    (((s8) (c) >= -128) && ((s8) (c) <= 127))
+
+# define IS_IMM32(c) \
+    (((s8) (c) >= (-2147483647-1)) && ((s8) (c) <= 2147483647))
+
+#else
+
+# define IS_IMM8(c) \
+    (((s4) (c) >= -128) && ((s4) (c) <= 127))
+
+# define IS_IMM16(c) \
+    (((s4) (c) >= -32768) && ((s4) (c) <= 32767))
+
+#endif
+
+
+/* code generation functions **************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg);
+s4 emit_load_s1(jitdata *jd, instruction *iptr, s4 tempreg);
+s4 emit_load_s2(jitdata *jd, instruction *iptr, s4 tempreg);
+s4 emit_load_s3(jitdata *jd, instruction *iptr, s4 tempreg);
+
+#if SIZEOF_VOID_P == 4
+s4 emit_load_low(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg);
+s4 emit_load_s1_low(jitdata *jd, instruction *iptr, s4 tempreg);
+s4 emit_load_s2_low(jitdata *jd, instruction *iptr, s4 tempreg);
+s4 emit_load_s3_low(jitdata *jd, instruction *iptr, s4 tempreg);
+
+s4 emit_load_high(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg);
+s4 emit_load_s1_high(jitdata *jd, instruction *iptr, s4 tempreg);
+s4 emit_load_s2_high(jitdata *jd, instruction *iptr, s4 tempreg);
+s4 emit_load_s3_high(jitdata *jd, instruction *iptr, s4 tempreg);
+#endif
+
+void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d);
+void emit_store_dst(jitdata *jd, instruction *iptr, s4 d);
+
+#if SIZEOF_VOID_P == 4
+void emit_store_low(jitdata *jd, instruction *iptr, varinfo *dst, s4 d);
+void emit_store_high(jitdata *jd, instruction *iptr, varinfo *dst, s4 d);
+#endif
+
+void emit_copy(jitdata *jd, instruction *iptr);
+
+void emit_iconst(codegendata *cd, s4 d, s4 value);
+void emit_lconst(codegendata *cd, s4 d, s8 value);
+
+/* branch-emitting functions */
+void emit_bccz(codegendata *cd, basicblock *target, s4 condition, s4 reg, u4 options);
+void emit_bcc(codegendata *cd, basicblock *target, s4 condition, u4 options);
+
+/* wrapper for unconditional branches */
+void emit_br(codegendata *cd, basicblock *target);
+
+/* wrappers for branches on one integer register */
+
+#if SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER
+void emit_beqz(codegendata *cd, basicblock *target, s4 reg);
+void emit_bnez(codegendata *cd, basicblock *target, s4 reg);
+void emit_bltz(codegendata *cd, basicblock *target, s4 reg);
+void emit_bgez(codegendata *cd, basicblock *target, s4 reg);
+void emit_bgtz(codegendata *cd, basicblock *target, s4 reg);
+void emit_blez(codegendata *cd, basicblock *target, s4 reg);
+#endif
+
+/* wrappers for branches on two integer registers */
+
+#if SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS
+void emit_beq(codegendata *cd, basicblock *target, s4 s1, s4 s2);
+void emit_bne(codegendata *cd, basicblock *target, s4 s1, s4 s2);
+#endif
+
+/* wrappers for branches on condition codes */
+
+#if SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER
+void emit_beq(codegendata *cd, basicblock *target);
+void emit_bne(codegendata *cd, basicblock *target);
+void emit_blt(codegendata *cd, basicblock *target);
+void emit_bge(codegendata *cd, basicblock *target);
+void emit_bgt(codegendata *cd, basicblock *target);
+void emit_ble(codegendata *cd, basicblock *target);
+#endif
+
+#if SUPPORT_BRANCH_CONDITIONAL_UNSIGNED_CONDITIONS
+void emit_bult(codegendata *cd, basicblock *target);
+void emit_bule(codegendata *cd, basicblock *target);
+void emit_buge(codegendata *cd, basicblock *target);
+void emit_bugt(codegendata *cd, basicblock *target);
+#endif
+
+#if defined(__POWERPC__) || defined(__POWERPC64__)
+void emit_bnan(codegendata *cd, basicblock *target);
+#endif
+
+/* label-branches */
+void emit_label_bccz(codegendata *cd, s4 label, s4 condition, s4 reg, u4 options);
+void emit_label(codegendata *cd, s4 label);
+void emit_label_bcc(codegendata *cd, s4 label, s4 condition, u4 options);
+
+void emit_label_br(codegendata *cd, s4 label);
+
+#if SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER
+void emit_label_beqz(codegendata *cd, s4 label, s4 reg);
+#endif
+
+#if SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER
+void emit_label_beq(codegendata *cd, s4 label);
+void emit_label_bne(codegendata *cd, s4 label);
+void emit_label_blt(codegendata *cd, s4 label);
+void emit_label_bge(codegendata *cd, s4 label);
+void emit_label_bgt(codegendata *cd, s4 label);
+void emit_label_ble(codegendata *cd, s4 label);
+#endif
+
+/* machine dependent branch-emitting function */
+void emit_branch(codegendata *cd, s4 disp, s4 condition, s4 reg, u4 options);
+
+void emit_arithmetic_check(codegendata *cd, instruction *iptr, s4 reg);
+void emit_arrayindexoutofbounds_check(codegendata *cd, instruction *iptr, s4 s1, s4 s2);
+void emit_arraystore_check(codegendata *cd, instruction *iptr);
+void emit_classcast_check(codegendata *cd, instruction *iptr, s4 condition, s4 reg, s4 s1);
+void emit_nullpointer_check(codegendata *cd, instruction *iptr, s4 reg);
+void emit_exception_check(codegendata *cd, instruction *iptr);
+
+void emit_trap_compiler(codegendata *cd);
+void emit_trap_countdown(codegendata *cd, s4 *counter);
+uint32_t emit_trap(codegendata *cd);
+
+void emit_patcher_traps(jitdata *jd);
+
+void emit_verbosecall_enter(jitdata *jd);
+void emit_verbosecall_exit(jitdata *jd);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _EMIT_COMMON_H */
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
index 102f455149a7ace0650b50342fb1bb954cb68b73..9130543d24762d806416a9e9774bd7369b3ddd33 100644 (file)
@@ -30,9 +30,9 @@
 
 #include "mm/memory.h"
 
-#include "vm/jit/code.h"
+#include "vm/jit/code.hpp"
 #include "vm/jit/exceptiontable.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
 
 
 /* exceptiontable_create *******************************************************
index 903b250f26125de9c673263c0243cab151b384d9..d4733aefba4de85cef912646b7d053c0932e511a 100644 (file)
@@ -36,8 +36,8 @@ typedef struct exceptiontable_entry_t exceptiontable_entry_t;
 
 #include <stdint.h>
 
-#include "vm/jit/code.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/code.hpp"
+#include "vm/jit/jit.hpp"
 
 
 /* exceptiontable_t ***********************************************************/
@@ -60,6 +60,10 @@ struct exceptiontable_entry_t {
 
 /* function prototypes ********************************************************/
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 void exceptiontable_create(jitdata *jd);
 void exceptiontable_free(codeinfo *code);
 
@@ -67,6 +71,10 @@ void exceptiontable_free(codeinfo *code);
 void exceptiontable_print(codeinfo *code);
 #endif
 
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
 #endif /* _EXCEPTIONTABLE_H */
 
 
index 722922ce4f839e62b46297b31c20e4bef2d2e666..cfcac31c3dc4e1a5b114b35a39427448dd0e9948 100644 (file)
@@ -221,11 +221,7 @@ void executionstate_println(executionstate_t *es)
                        if (i%4 == 0)
                                printf("\n\t\t");
                        printf("M%02d%c", i, (i >= slots) ? '(' : ' ');
-#ifdef HAS_4BYTE_STACKSLOT
-                       printf("%08lx",(unsigned long)*sp++);
-#else
                        printf("%016llx",(unsigned long long)*sp++);
-#endif
                        printf("%c", (i >= slots) ? ')' : ' ');
                }
                printf("\n");
index 46211e722eecceb90767ddf30597a3bc174aea6b..59e14ea4be23ef7e8ce7c6c47e12e0feff8842f5 100644 (file)
@@ -38,7 +38,7 @@ typedef struct executionstate_t executionstate_t;
 #include "arch.h"
 #include "md-abi.h"
 
-#include "vm/jit/code.h"
+#include "vm/jit/code.hpp"
 
 
 /* executionstate_t ************************************************************
@@ -68,6 +68,10 @@ struct executionstate_t {
 
 /* prototypes *****************************************************************/
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #if !defined(NDEBUG)
 void executionstate_sanity_check(void *context);
 void executionstate_println(executionstate_t *es);
@@ -78,6 +82,10 @@ void executionstate_println(executionstate_t *es);
 void md_executionstate_read(executionstate_t *es, void *ucontext);
 void md_executionstate_write(executionstate_t *es, void *ucontext);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* _EXECUTIONSTATE_H */
 
 
index 044e950af353558577d4847c93b032600bf28ed5..044070caf81ba6a780d7ca8040367fb3bf121bb4 100644 (file)
@@ -58,6 +58,7 @@ libarch_la_SOURCES = \
        \
        md-abi.c \
        md-abi.h \
+       md-stubs.hpp \
        md-trap.h \
        md.c \
        md.h
index 9d68a824cb9dc77a6d3424bc04354d1ae37cc107..d5d71e803b16127c5de2c7b5e152dedb7c7b0073 100644 (file)
@@ -46,8 +46,6 @@
 
 /* define architecture features ***********************************************/
 
-#define U8_AVAILABLE                     1
-
 #define SUPPORT_DIVISION                 1
 #define SUPPORT_LONG                     1
 
index 133b1bf61e60e826d136d0ea4e8384bbf4226f61..b7e808cabc8f7ecaa927bb0ea5b0bb89c9e6e26a 100644 (file)
 #include "vm/jit/i386/emit.h"
 
 #include "mm/memory.h"
-#include "native/jni.h"
-#include "native/localref.h"
-#include "native/native.h"
 
-#include "threads/lock-common.h"
+#include "native/localref.hpp"
+#include "native/native.hpp"
 
-#include "vm/builtin.h"
+#include "threads/lock.hpp"
+
+#include "vm/jit/builtin.hpp"
 #include "vm/exceptions.hpp"
 #include "vm/global.h"
-#include "vm/loader.h"
+#include "vm/loader.hpp"
 #include "vm/options.h"
 #include "vm/primitive.hpp"
 #include "vm/utf8.h"
 
 #include "vm/jit/abi.h"
 #include "vm/jit/asmpart.h"
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/codegen-common.hpp"
 #include "vm/jit/dseg.h"
-#include "vm/jit/emit-common.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/emit-common.hpp"
+#include "vm/jit/jit.hpp"
 #include "vm/jit/jitcache.hpp"
-#include "vm/jit/linenumbertable.h"
+#include "vm/jit/linenumbertable.hpp"
 #include "vm/jit/parse.h"
-#include "vm/jit/patcher-common.h"
+#include "vm/jit/patcher-common.hpp"
 #include "vm/jit/reg.h"
-#include "vm/jit/replace.h"
+#include "vm/jit/replace.hpp"
 #include "vm/jit/stacktrace.hpp"
 #include "vm/jit/trap.h"
 
index eb7ab8047fe76c0ef7479e827d5ee16aedff7b25..2efb24532981093b2619f8ef40198b84ae0c039c 100644 (file)
@@ -1,9 +1,7 @@
 /* src/vm/jit/i386/codegen.h - code generation macros and definitions for i386
 
-   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
-   C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
-   E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
-   J. Wenninger, Institut f. Computersprachen - TU Wien
+   Copyright (C) 1996-2005, 2006, 2007, 2008
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
 
@@ -33,7 +31,7 @@
 
 #include "vm/jit/i386/emit.h"
 
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
 
 
 #if defined(ENABLE_LSRA)
     } while (0)
 
 
-/* stub defines ***************************************************************/
-
-#define COMPILERSTUB_CODESIZE    6
-
-
 /* macros to create code ******************************************************/
 
 #define M_BYTE1(a) \
index 3737b0144f1dcb3800e9338aa7a190e0e17026ab..87157e5009984fac885e9903971efb261fd67628 100644 (file)
@@ -37,7 +37,7 @@
 
 #include "threads/thread.hpp"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/global.h"
 #include "vm/signallocal.h"
 
@@ -72,7 +72,6 @@ void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
        intptr_t             val;
        int                  type;
        void                *p;
-       java_object_t       *o;
 
        _uc = (ucontext_t *) _p;
        _mc = _uc->uc_mcontext;
@@ -142,23 +141,9 @@ void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
        /* Set registers. */
 
        if (type == TRAP_COMPILER) {
-               if (p == NULL) { 
-                       o = builtin_retrieve_exception();
-
+               if (p == NULL) {
                        _ss->__esp = (uintptr_t) sp;  /* Remove RA from stack. */
-
-                       _ss->__eax = (uintptr_t) o;
-                       _ss->__ecx = (uintptr_t) xpc;           /* REG_ITMP2_XPC */
-                       _ss->__eip = (uintptr_t) asm_handle_exception;
                }
-               else {
-                       _ss->__eip = (uintptr_t) p;
-               }
-       }
-       else {
-               _ss->__eax = (uintptr_t) p;
-               _ss->__ecx = (uintptr_t) xpc;            /* REG_ITMP2_XPC */
-               _ss->__eip = (uintptr_t) asm_handle_exception;
        }
 }
 
@@ -181,7 +166,6 @@ void md_signal_handler_sigfpe(int sig, siginfo_t *siginfo, void *_p)
        u1                  *xpc;
        int                  type;
        intptr_t             val;
-       void                *p;
 
 
        _uc = (ucontext_t *) _p;
@@ -200,13 +184,7 @@ void md_signal_handler_sigfpe(int sig, siginfo_t *siginfo, void *_p)
 
        /* Handle the trap. */
 
-       p = trap_handle(type, val, pv, sp, ra, xpc, _p);
-
-       /* Set registers. */
-
-       _ss->__eax = (uintptr_t) p;
-       _ss->__ecx = (uintptr_t) xpc;            /* REG_ITMP2_XPC */
-       _ss->__eip = (uintptr_t) asm_handle_exception;
+       trap_handle(type, val, pv, sp, ra, xpc, _p);
 }
 
 
@@ -253,7 +231,6 @@ void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p)
        u1                  *xpc;
        int                  type;
        intptr_t             val;
-       void                *p;
 
 
        _uc = (ucontext_t *) _p;
@@ -270,15 +247,7 @@ void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p)
 
        /* Handle the trap. */
 
-       p = trap_handle(type, val, pv, sp, ra, xpc, _p);
-
-       /* Set registers. */
-
-       if (p != NULL) {
-               _ss->__eax = (uintptr_t) p;
-               _ss->__ecx = (uintptr_t) xpc;            /* REG_ITMP2_XPC */
-               _ss->__eip = (uintptr_t) asm_handle_exception;
-       }
+       trap_handle(type, val, pv, sp, ra, xpc, _p);
 }
 
 /* md_executionstate_read ******************************************************
index a23d4c0e60a1b3bd4a2f3fd702b7c5de982a8031..ca730f3b60a944af9ec7af715c3196a8bb11b25f 100644 (file)
@@ -35,7 +35,7 @@
 
 #include "mm/memory.h"
 
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
 
 #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/emit-common.h"
-#include "vm/jit/jit.h"
-#include "vm/jit/patcher-common.h"
-#include "vm/jit/replace.h"
+#include "vm/jit/emit-common.hpp"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/patcher-common.hpp"
+#include "vm/jit/replace.hpp"
 #include "vm/jit/trace.hpp"
 #include "vm/jit/trap.h"
 
index 8082aab78459e68b3e109c827dcd1dcd27f21887..56bd05a6547aa1b9ac10b18319d4055ed7dbdfc5 100644 (file)
@@ -36,7 +36,7 @@
 
 #include "vm/types.h"
 
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/codegen-common.hpp"
 
 
 #define REG_AL       0
index b3ec691f21d64bc37a327cb9fbf3416a79f5361d..9a1dc9d5eaedd2ac8ec652d873bfcc4e297b54d1 100644 (file)
@@ -1,6 +1,6 @@
 /* src/vm/jit/i386/freebsd/md-os.c - machine dependent i386 FreeBSD functions
 
-   Copyright (C) 1996-2005, 2006, 2008
+   Copyright (C) 1996-2005, 2006, 2007, 2008
    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
 
 #include "config.h"
 
+#include <stdint.h>
 #include <ucontext.h>
 
-#include "vm/jit/i386/md-abi.h"
+#include "vm/types.h"
 
+#include "vm/jit/i386/codegen.h"
+#include "vm/jit/i386/md.h"
+
+#include "threads/thread.hpp"
+
+#include "vm/jit/builtin.hpp"
 #include "vm/signallocal.h"
+
 #include "vm/jit/asmpart.h"
+#include "vm/jit/executionstate.h"
 #include "vm/jit/stacktrace.hpp"
+#include "vm/jit/trap.h"
 
 
 /* md_signal_handler_sigsegv ***************************************************
 
-   NullPointerException signal handler for hardware null pointer
-   check.
+   Signal handler for hardware exceptions.
 
 *******************************************************************************/
 
 void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
 {
-       ucontext_t *_uc;
-       mcontext_t *_mc;
-       u1         *sp;
-       u1         *ra;
-       u1         *xpc;
+       ucontext_t     *_uc;
+       mcontext_t     *_mc;
+       u1             *pv;
+       u1             *sp;
+       u1             *ra;
+       u1             *xpc;
+       u1              opc;
+       u1              mod;
+       u1              rm;
+       s4              d;
+       s4              disp;
+       ptrint          val;
+       s4              type;
+       void           *p;
 
        _uc = (ucontext_t *) _p;
        _mc = &_uc->uc_mcontext;
-       
+
+       pv  = NULL;                 /* is resolved during stackframeinfo creation */
        sp  = (u1 *) _mc->mc_esp;
        xpc = (u1 *) _mc->mc_eip;
-       ra  = xpc;                          /* return address is equal to xpc     */
+       ra  = xpc;                              /* return address is equal to XPC */
+
+       /* get exception-throwing instruction */
+
+       opc = M_ALD_MEM_GET_OPC(xpc);
+       mod = M_ALD_MEM_GET_MOD(xpc);
+       rm  = M_ALD_MEM_GET_RM(xpc);
+
+       /* for values see emit_mov_mem_reg and emit_mem */
+
+       if ((opc == 0x8b) && (mod == 0) && (rm == 5)) {
+               /* this was a hardware-exception */
+
+               d    = M_ALD_MEM_GET_REG(xpc);
+               disp = M_ALD_MEM_GET_DISP(xpc);
+
+               /* we use the exception type as load displacement */
+
+               type = disp;
+
+               switch (d) {
+               case EAX:
+                       val = _mc->mc_eax;
+                       break;
+               case ECX:
+                       val = _mc->mc_ecx;
+                       break;
+               case EDX:
+                       val = _mc->mc_edx;
+                       break;
+               case EBX:
+                       val = _mc->mc_ebx;
+                       break;
+               case ESP:
+                       val = _mc->mc_esp;
+                       break;
+               case EBP:
+                       val = _mc->mc_ebp;
+                       break;
+               case ESI:
+                       val = _mc->mc_esi;
+                       break;
+               case EDI:
+                       val = _mc->mc_edi;
+                       break;
+               default:
+                       vm_abort("md_signal_handler_sigsegv: Unkown register %d", d);
+               }
+
+               if (type == TRAP_COMPILER) {
+                       /* The PV from the compiler stub is equal to the XPC. */
+
+                       pv = xpc;
+
+                       /* We use a framesize of zero here because the call pushed
+                          the return addres onto the stack. */
+
+                       ra = md_stacktrace_get_returnaddress(sp, 0);
+
+                       /* Skip the RA on the stack. */
+
+                       sp = sp + 1 * SIZEOF_VOID_P;
+
+                       /* The XPC is the RA minus 2, because the RA points to the
+                          instruction after the call. */
+
+                       xpc = ra - 2;
+               }
+       }
+       else {
+               /* this was a normal NPE */
+
+               type = TRAP_NullPointerException;
+               val  = 0;
+       }
 
-       _mc->mc_eax =
-               (ptrint) stacktrace_hardware_nullpointerexception(NULL, sp, ra, xpc);
-       
-       _mc->mc_ecx = (ptrint) xpc;                              /* REG_ITMP2_XPC */
-       _mc->mc_eip = (ptrint) asm_handle_exception;
+       /* Handle the trap. */
+
+       p = trap_handle(type, val, pv, sp, ra, xpc, _p);
+
+       /* Set registers. */
+
+       if (type == TRAP_COMPILER) {
+               if (p == NULL) {
+                       _mc->mc_esp = (uintptr_t) sp; // Remove RA from stack.
+               }
+       }
 }
 
 
@@ -73,24 +172,177 @@ void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
 
 void md_signal_handler_sigfpe(int sig, siginfo_t *siginfo, void *_p)
 {
-       ucontext_t *_uc;
-       mcontext_t *_mc;
-       u1         *sp;
-       u1         *ra;
-       u1         *xpc;
+       ucontext_t     *_uc;
+       mcontext_t     *_mc;
+       u1             *pv;
+       u1             *sp;
+       u1             *ra;
+       u1             *xpc;
+       s4              type;
+       ptrint          val;
 
        _uc = (ucontext_t *) _p;
        _mc = &_uc->uc_mcontext;
 
+       pv  = NULL;                 /* is resolved during stackframeinfo creation */
        sp  = (u1 *) _mc->mc_esp;
        xpc = (u1 *) _mc->mc_eip;
        ra  = xpc;                          /* return address is equal to xpc     */
 
-       _mc->mc_eax =
-               (ptrint) stacktrace_hardware_arithmeticexception(NULL, sp, ra, xpc);
-       
-       _mc->mc_ecx = (ptrint) xpc;                              /* REG_ITMP2_XPC */
-       _mc->mc_eip = (ptrint) asm_handle_exception;
+       /* This is an ArithmeticException. */
+
+       type = TRAP_ArithmeticException;
+       val  = 0;
+
+       /* Handle the trap. */
+
+       trap_handle(type, val, pv, sp, ra, xpc, _p);
+}
+
+
+/* md_signal_handler_sigill ****************************************************
+
+   Signal handler for hardware patcher traps (ud2).
+
+*******************************************************************************/
+
+void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p)
+{
+       ucontext_t        *_uc;
+       mcontext_t        *_mc;
+       u1                *pv;
+       u1                *sp;
+       u1                *ra;
+       u1                *xpc;
+       s4                 type;
+       ptrint             val;
+
+       _uc = (ucontext_t *) _p;
+       _mc = &_uc->uc_mcontext;
+
+       pv  = NULL;                 /* is resolved during stackframeinfo creation */
+       sp  = (u1 *) _mc->mc_esp;
+       xpc = (u1 *) _mc->mc_eip;
+       ra  = xpc;                            /* return address is equal to xpc   */
+
+       type = TRAP_PATCHER;
+       val  = 0;
+
+       /* Handle the trap. */
+
+       trap_handle(type, val, pv, sp, ra, xpc, _p);
+}
+
+
+/* md_signal_handler_sigusr1 ***************************************************
+
+   Signal handler for suspending threads.
+
+*******************************************************************************/
+
+#if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
+void md_signal_handler_sigusr1(int sig, siginfo_t *siginfo, void *_p)
+{
+       ucontext_t *_uc;
+       mcontext_t *_mc;
+       u1         *pc;
+       u1         *sp;
+
+       _uc = (ucontext_t *) _p;
+       _mc = &_uc->uc_mcontext;
+
+       /* get the PC and SP for this thread */
+       pc = (u1 *) _mc->mc_eip;
+       sp = (u1 *) _mc->mc_esp;
+
+       /* now suspend the current thread */
+       threads_suspend_ack(pc, sp);
+}
+#endif
+
+
+/* md_signal_handler_sigusr2 ***************************************************
+
+   Signal handler for profiling sampling.
+
+*******************************************************************************/
+
+#if defined(ENABLE_THREADS)
+void md_signal_handler_sigusr2(int sig, siginfo_t *siginfo, void *_p)
+{
+       threadobject *t;
+       ucontext_t   *_uc;
+       mcontext_t   *_mc;
+       u1           *pc;
+
+       t = THREADOBJECT;
+
+       _uc = (ucontext_t *) _p;
+       _mc = &_uc->uc_mcontext;
+
+       pc = (u1 *) _mc->mc_eip;
+
+       t->pc = pc;
+}
+#endif
+
+
+/* md_executionstate_read ******************************************************
+
+   Read the given context into an executionstate for Replacement.
+
+*******************************************************************************/
+
+void md_executionstate_read(executionstate_t* es, void* context)
+{
+       ucontext_t* _uc = (ucontext_t*) context;
+       mcontext_t* _mc = &_uc->uc_mcontext;
+
+       // Read special registers.
+       es->pc = (u1 *) _mc->mc_eip;
+       es->sp = (u1 *) _mc->mc_esp;
+       es->pv = NULL;                   /* pv must be looked up via AVL tree */
+
+       // Read integer registers.
+       es->intregs[EAX] = _mc->mc_eax;
+       es->intregs[ECX] = _mc->mc_ecx;
+       es->intregs[EDX] = _mc->mc_edx;
+       es->intregs[EBX] = _mc->mc_ebx;
+       es->intregs[ESP] = _mc->mc_esp;
+       es->intregs[EBP] = _mc->mc_ebp;
+       es->intregs[ESI] = _mc->mc_esi;
+       es->intregs[EDI] = _mc->mc_edi;
+
+       // Read float registers.
+       for (int i = 0; i < FLT_REG_CNT; i++)
+               es->fltregs[i] = 0xdeadbeefdeadbeefULL;
+}
+
+
+/* md_executionstate_write *****************************************************
+
+   Write the given executionstate back to the context for Replacement.
+
+*******************************************************************************/
+
+void md_executionstate_write(executionstate_t* es, void* context)
+{
+       ucontext_t* _uc = (ucontext_t*) context;
+       mcontext_t* _mc = &_uc->uc_mcontext;
+
+       // Write integer registers.
+       _mc->mc_eax = es->intregs[EAX];
+       _mc->mc_ecx = es->intregs[ECX];
+       _mc->mc_edx = es->intregs[EDX];
+       _mc->mc_ebx = es->intregs[EBX];
+       _mc->mc_esp = es->intregs[ESP];
+       _mc->mc_ebp = es->intregs[EBP];
+       _mc->mc_esi = es->intregs[ESI];
+       _mc->mc_edi = es->intregs[EDI];
+
+       // Write special registers.
+       _mc->mc_eip = (uintptr_t) es->pc;
+       _mc->mc_esp = (uintptr_t) es->sp;
 }
 
 
index 97c362f4e081e0b8c3cfe7b7384189958926bb95..f046f37d6cfbddacd0746d1706ec511cf416d36c 100644 (file)
@@ -37,7 +37,7 @@
 
 #include "threads/thread.hpp"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/signallocal.h"
 
 #include "vm/jit/asmpart.h"
@@ -68,7 +68,6 @@ void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
        ptrint          val;
        s4              type;
        void           *p;
-       java_object_t  *o;
 
        _uc = (ucontext_t *) _p;
        _mc = &_uc->uc_mcontext;
@@ -138,28 +137,9 @@ void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
 
        if (type == TRAP_COMPILER) {
                if (p == NULL) {
-                       o = builtin_retrieve_exception();
-
                        _mc->gregs[REG_ESP] = (uintptr_t) sp;    /* Remove RA from stack. */
-
-                       _mc->gregs[REG_EAX] = (uintptr_t) o;
-                       _mc->gregs[REG_ECX] = (uintptr_t) xpc;           /* REG_ITMP2_XPC */
-                       _mc->gregs[REG_EIP] = (uintptr_t) asm_handle_exception;
-               }
-               else {
-                       _mc->gregs[REG_EIP] = (uintptr_t) p;
                }
        }
-#if defined(ENABLE_REPLACEMENT)
-       else if (type == TRAP_COUNTDOWN) {
-               /* context has been written by md_replace_executionstate_write */
-       }
-#endif
-       else {
-               _mc->gregs[REG_EAX] = (uintptr_t) p;
-               _mc->gregs[REG_ECX] = (uintptr_t) xpc;               /* REG_ITMP2_XPC */
-               _mc->gregs[REG_EIP] = (uintptr_t) asm_handle_exception;
-       }
 }
 
 
@@ -180,7 +160,6 @@ void md_signal_handler_sigfpe(int sig, siginfo_t *siginfo, void *_p)
        u1             *xpc;
        s4              type;
        ptrint          val;
-       void           *p;
 
        _uc = (ucontext_t *) _p;
        _mc = &_uc->uc_mcontext;
@@ -197,13 +176,7 @@ void md_signal_handler_sigfpe(int sig, siginfo_t *siginfo, void *_p)
 
        /* Handle the trap. */
 
-       p = trap_handle(type, val, pv, sp, ra, xpc, _p);
-
-       /* Set registers. */
-
-       _mc->gregs[REG_EAX] = (uintptr_t) p;
-       _mc->gregs[REG_ECX] = (uintptr_t) xpc;                   /* REG_ITMP2_XPC */
-       _mc->gregs[REG_EIP] = (uintptr_t) asm_handle_exception;
+       trap_handle(type, val, pv, sp, ra, xpc, _p);
 }
 
 
@@ -223,7 +196,6 @@ void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p)
        u1                *xpc;
        s4                 type;
        ptrint             val;
-       void              *p;
 
        _uc = (ucontext_t *) _p;
        _mc = &_uc->uc_mcontext;
@@ -238,15 +210,7 @@ void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p)
 
        /* Handle the trap. */
 
-       p = trap_handle(type, val, pv, sp, ra, xpc, _p);
-
-       /* Set registers. */
-
-       if (p != NULL) {
-               _mc->gregs[REG_EAX] = (uintptr_t) p;
-               _mc->gregs[REG_ECX] = (uintptr_t) xpc;               /* REG_ITMP2_XPC */
-               _mc->gregs[REG_EIP] = (uintptr_t) asm_handle_exception;
-       }
+       trap_handle(type, val, pv, sp, ra, xpc, _p);
 }
 
 
diff --git a/src/vm/jit/i386/md-stubs.hpp b/src/vm/jit/i386/md-stubs.hpp
new file mode 100644 (file)
index 0000000..c5ccf43
--- /dev/null
@@ -0,0 +1,56 @@
+/* src/vm/jit/i386/md-stubs.hpp - i386 JIT stubs
+
+   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 _MD_STUBS_HPP
+#define _MD_STUBS_HPP
+
+#include "config.h"
+
+
+/**
+ * Return the code size of a compiler on an i386 architecture.
+ *
+ * @return Code size in bytes.
+ */
+int CompilerStub::get_code_size()
+{
+       return 6;
+}
+
+#endif // _MD_STUBS_HPP
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
index cc93cd855bcb5cbc64250d54f4c0b70144be520c..191cddabd02cdb6d88b8b99a1b62b38dd6598c02 100644 (file)
@@ -34,7 +34,7 @@
 #include "vm/vm.hpp"
 
 #include "vm/jit/asmpart.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
 
 
 /* md_init *********************************************************************
index 568f8e934d0115ac9bb15754eedc4e32cbb2346e..562736be4f66d47c4fb2fd343d16a7d75a525a48 100644 (file)
@@ -31,7 +31,7 @@
 #include <assert.h>
 #include <stdint.h>
 
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/codegen-common.hpp"
 #include "vm/jit/methodtree.h"
 
 
@@ -85,7 +85,8 @@ inline static void *md_codegen_get_pv_from_pc(void *ra)
 
 inline static void md_cacheflush(void *addr, int nbytes)
 {
-       /* do nothing */
+       // Compiler optimization barrier (see PR97).
+       __asm__ __volatile__ ("" : : : "memory");
 }
 
 
@@ -97,7 +98,8 @@ inline static void md_cacheflush(void *addr, int nbytes)
 
 inline static void md_icacheflush(void *addr, int nbytes)
 {
-       /* do nothing */
+       // Compiler optimization barrier (see PR97).
+       __asm__ __volatile__ ("" : : : "memory");
 }
 
 
@@ -109,7 +111,8 @@ inline static void md_icacheflush(void *addr, int nbytes)
 
 inline static void md_dcacheflush(void *addr, int nbytes)
 {
-       /* do nothing */
+       // Compiler optimization barrier (see PR97).
+       __asm__ __volatile__ ("" : : : "memory");
 }
 
 #endif /* _VM_JIT_I386_MD_H */
index 3befeff5d96855818fd3dd2588beff84ebaf9212..19b91971803a6c59d1c2f0a9f04dac19662a7e9d 100644 (file)
 #include "vm/types.h"
 
 #include "vm/jit/i386/codegen.h"
+#include "vm/jit/i386/md.h"
 
 #include "mm/memory.h"
 
-#include "native/native.h"
+#include "native/native.hpp"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/class.h"
-#include "vm/field.h"
+#include "vm/field.hpp"
 #include "vm/initialize.h"
 #include "vm/options.h"
 #include "vm/references.h"
 #include "vm/resolve.h"
 
-#include "vm/jit/patcher-common.h"
+#include "vm/jit/patcher-common.hpp"
 
 
-#define PATCH_BACK_ORIGINAL_MCODE *((u2 *) pr->mpc) = (u2) pr->mcode
+#define PATCH_BACK_ORIGINAL_MCODE                                                      \
+       do {                                                                                                    \
+               *((uint16_t*) pr->mpc) = (uint16_t) pr->mcode;          \
+               md_icacheflush((void*) pr->mpc, PATCHER_CALL_SIZE);     \
+       } while (0)
 
 
 /* patcher_patch_code **********************************************************
@@ -94,11 +99,6 @@ bool patcher_get_putstatic(patchref_t *pr)
 
        PATCH_BACK_ORIGINAL_MCODE;
 
-       /* if we show disassembly, we have to skip the nop's */
-
-       if (opt_shownops)
-               ra = ra + PATCHER_CALL_SIZE;
-
        /* patch the field value's address */
 
        *((intptr_t *) (ra + 1)) = (intptr_t) fi->value;
@@ -134,11 +134,6 @@ bool patcher_getfield(patchref_t *pr)
 
        PATCH_BACK_ORIGINAL_MCODE;
 
-       /* if we show disassembly, we have to skip the nop's */
-
-       if (opt_shownops)
-               ra = ra + PATCHER_CALL_SIZE;
-
        /* patch the field's offset */
 
        *((u4 *) (ra + 2)) = (u4) (fi->offset);
@@ -179,11 +174,6 @@ bool patcher_putfield(patchref_t *pr)
 
        PATCH_BACK_ORIGINAL_MCODE;
 
-       /* if we show disassembly, we have to skip the nop's */
-
-       if (opt_shownops)
-               ra = ra + PATCHER_CALL_SIZE;
-
        /* patch the field's offset */
 
        if (fi->type != TYPE_LNG) {
@@ -231,11 +221,6 @@ bool patcher_putfieldconst(patchref_t *pr)
 
        PATCH_BACK_ORIGINAL_MCODE;
 
-       /* if we show disassembly, we have to skip the nop's */
-
-       if (opt_shownops)
-               ra = ra + PATCHER_CALL_SIZE;
-
        /* patch the field's offset */
 
        if (!IS_2_WORD_TYPE(fi->type)) {
@@ -284,11 +269,6 @@ bool patcher_aconst(patchref_t *pr)
 
        PATCH_BACK_ORIGINAL_MCODE;
 
-       /* if we show disassembly, we have to skip the nop's */
-
-       if (opt_shownops)
-               ra = ra + PATCHER_CALL_SIZE;
-
        /* patch the classinfo pointer */
 
        *((ptrint *) (ra + 1)) = (ptrint) c;
@@ -330,11 +310,6 @@ bool patcher_builtin_multianewarray(patchref_t *pr)
 
        PATCH_BACK_ORIGINAL_MCODE;
 
-       /* if we show disassembly, we have to skip the nop's */
-
-       if (opt_shownops)
-               ra = ra + PATCHER_CALL_SIZE;
-
        /* patch the classinfo pointer */
 
        *((ptrint *) (ra + 7 + 4)) = (ptrint) c;
@@ -372,11 +347,6 @@ bool patcher_builtin_arraycheckcast(patchref_t *pr)
 
        PATCH_BACK_ORIGINAL_MCODE;
 
-       /* if we show disassembly, we have to skip the nop's */
-
-       if (opt_shownops)
-               ra = ra + PATCHER_CALL_SIZE;
-
        /* patch the classinfo pointer */
 
        *((ptrint *) (ra + 4)) = (ptrint) c;
@@ -417,11 +387,6 @@ bool patcher_invokestatic_special(patchref_t *pr)
 
        PATCH_BACK_ORIGINAL_MCODE;
 
-       /* if we show disassembly, we have to skip the nop's */
-
-       if (opt_shownops)
-               ra = ra + PATCHER_CALL_SIZE;
-
        /* patch stubroutine */
 
        *((ptrint *) (ra + 1)) = (ptrint) m->stubroutine;
@@ -459,11 +424,6 @@ bool patcher_invokevirtual(patchref_t *pr)
 
        PATCH_BACK_ORIGINAL_MCODE;
 
-       /* if we show disassembly, we have to skip the nop's */
-
-       if (opt_shownops)
-               ra = ra + PATCHER_CALL_SIZE;
-
        /* patch vftbl index */
 
        *((s4 *) (ra + 2 + 2)) = (s4) (OFFSET(vftbl_t, table[0]) +
@@ -503,11 +463,6 @@ bool patcher_invokeinterface(patchref_t *pr)
 
        PATCH_BACK_ORIGINAL_MCODE;
 
-       /* if we show disassembly, we have to skip the nop's */
-
-       if (opt_shownops)
-               ra = ra + PATCHER_CALL_SIZE;
-
        /* patch interfacetable index */
 
        *((s4 *) (ra + 2 + 2)) = (s4) (OFFSET(vftbl_t, interfacetable[0]) -
@@ -549,11 +504,6 @@ bool patcher_checkcast_instanceof_flags(patchref_t *pr)
 
        PATCH_BACK_ORIGINAL_MCODE;
 
-       /* if we show disassembly, we have to skip the nop's */
-
-       if (opt_shownops)
-               ra = ra + PATCHER_CALL_SIZE;
-
        /* patch class flags */
 
        *((s4 *) (ra + 1)) = (s4) c->flags;
@@ -594,11 +544,6 @@ bool patcher_checkcast_interface(patchref_t *pr)
 
        PATCH_BACK_ORIGINAL_MCODE;
 
-       /* if we show disassembly, we have to skip the nop's */
-
-       if (opt_shownops)
-               ra = ra + PATCHER_CALL_SIZE;
-
        /* patch super class index */
 
        *((s4 *) (ra + 6 + 2)) = (s4) c->index;
@@ -642,11 +587,6 @@ bool patcher_instanceof_interface(patchref_t *pr)
 
        PATCH_BACK_ORIGINAL_MCODE;
 
-       /* if we show disassembly, we have to skip the nop's */
-
-       if (opt_shownops)
-               ra = ra + PATCHER_CALL_SIZE;
-
        /* patch super class index */
 
        *((s4 *) (ra + 6 + 2)) = (s4) c->index;
@@ -690,11 +630,6 @@ bool patcher_checkcast_class(patchref_t *pr)
 
        PATCH_BACK_ORIGINAL_MCODE;
 
-       /* if we show disassembly, we have to skip the nop's */
-
-       if (opt_shownops)
-               ra = ra + PATCHER_CALL_SIZE;
-
        /* patch super class' vftbl */
 
        *((ptrint *) (ra + 1)) = (ptrint) c->vftbl;
@@ -734,11 +669,6 @@ bool patcher_instanceof_class(patchref_t *pr)
 
        PATCH_BACK_ORIGINAL_MCODE;
 
-       /* if we show disassembly, we have to skip the nop's */
-
-       if (opt_shownops)
-               ra = ra + PATCHER_CALL_SIZE;
-
        /* patch super class' vftbl */
 
        *((ptrint *) (ra + 1)) = (ptrint) c->vftbl;
index bc95947bb7a16f270eab300f7733cd80d39e3759..67363ec8d5c45948e7232997ca1f78a6d6a7a16e 100644 (file)
@@ -35,7 +35,7 @@
 
 #include "threads/thread.hpp"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/signallocal.h"
 
 #include "vm/jit/asmpart.h"
@@ -66,7 +66,6 @@ void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
        ptrint          val;
        s4              type;
        void           *p;
-       java_object_t  *o;
 
        _uc = (ucontext_t *) _p;
        _mc = &_uc->uc_mcontext;
@@ -136,23 +135,9 @@ void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
 
        if (type == TRAP_COMPILER) {
                if (p == NULL) {
-                       o = builtin_retrieve_exception();
-
                        _mc->gregs[ESP] = (uintptr_t) sp;    /* Remove RA from stack. */
-
-                       _mc->gregs[EAX] = (uintptr_t) o;
-                       _mc->gregs[ECX] = (uintptr_t) xpc;           /* REG_ITMP2_XPC */
-                       _mc->gregs[EIP] = (uintptr_t) asm_handle_exception;
-               }
-               else {
-                       _mc->gregs[EIP] = (uintptr_t) p;
                }
        }
-       else {
-               _mc->gregs[EAX] = (uintptr_t) p;
-               _mc->gregs[ECX] = (uintptr_t) xpc;               /* REG_ITMP2_XPC */
-               _mc->gregs[EIP] = (uintptr_t) asm_handle_exception;
-       }
 }
 
 
@@ -173,7 +158,6 @@ void md_signal_handler_sigfpe(int sig, siginfo_t *siginfo, void *_p)
        u1         *xpc;
        s4          type;
        ptrint      val;
-       void       *p;
 
        _uc = (ucontext_t *) _p;
        _mc = &_uc->uc_mcontext;
@@ -190,13 +174,7 @@ void md_signal_handler_sigfpe(int sig, siginfo_t *siginfo, void *_p)
 
        /* Handle the trap. */
 
-       p = trap_handle(type, val, pv, sp, ra, xpc, _p);
-
-       /* Set registers. */
-
-       _mc->gregs[EAX] = (uintptr_t) p;
-       _mc->gregs[ECX] = (uintptr_t) xpc;                   /* REG_ITMP2_XPC */
-       _mc->gregs[EIP] = (uintptr_t) asm_handle_exception;
+       trap_handle(type, val, pv, sp, ra, xpc, _p);
 }
 
 
@@ -216,7 +194,6 @@ void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p)
        u1         *xpc;
        s4          type;
        ptrint      val;
-       void       *p;
 
        _uc = (ucontext_t *) _p;
        _mc = &_uc->uc_mcontext;
@@ -231,15 +208,7 @@ void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p)
 
        /* Handle the trap. */
 
-       p = trap_handle(type, val, pv, sp, ra, xpc, _p);
-
-       /* Set registers. */
-
-       if (p != NULL) {
-               _mc->gregs[EAX] = (uintptr_t) p;
-               _mc->gregs[ECX] = (uintptr_t) xpc;               /* REG_ITMP2_XPC */
-               _mc->gregs[EIP] = (uintptr_t) asm_handle_exception;
-       }
+       trap_handle(type, val, pv, sp, ra, xpc, _p);
 }
 
 
diff --git a/src/vm/jit/icmdtable.inc b/src/vm/jit/icmdtable.inc
deleted file mode 100644 (file)
index 4b0639c..0000000
+++ /dev/null
@@ -1,310 +0,0 @@
-/*** The ICMD Table ***/
-
-/* IMPORTANT: This file must be in a fixed format, as it is both included in */
-/* src/vm/jit/jit.c, and parsed by src/vm/jit/verify/generate.pl!            */
-/*                                                                           */
-/* The comments at the start of the line and inside the braces are           */
-/* significant. If you want to add a comment to an ICMD, do that after the   */
-/* comma, or brace, at the end of the line.                                  */
-/*                                                                           */
-/* The format is as follows (slashes reversed for obvious reasons):          */
-/*                                                                           */
-/* \*#*\ { N( name )  data-flow, control-flow, flags \* stage (action) *\ }  */
-/*                                                                           */
-/*  ^^^                                                                      */
-/* opcode                                                                    */
-/*                                                                           */
-/* where                                                                     */
-/*     opcode...........is the opcode number (decimal)                       */
-/*     name.............is the quoted name without the ICMD_ prefix          */
-/*     data-flow........is one of the DF_ constants (see jit.h)              */
-/*     control-flow.....is one of the CF_ constants (see jit.h)              */
-/*     flags............is 0 or a |-combination of                           */
-/*                          PEI........may throw an exception                */
-/*                          CALLS......needs saved registers (calls out)     */
-/*                          *_CALLS....see jit.h for architecture specific   */
-/*                                     constants to put here                 */
-/*                                                                           */
-/*     stage............is either empty, or one of                           */
-/*                          --         ICMD is not used anywhere after parse */
-/*                          -S         ICMD is eliminated by stack_analyse   */
-/*                          S+         ICMD is introduced by stack_analyse   */
-/*                                                                           */
-/*     action...........is the stack action of the ICMD in the notation      */
-/*                      instack--outstack, TOS being rightmost.              */
-/*                                                                           */
-/*                      Valid type characters are                            */
-/*                          I, L, F, D, and A      the basic types           */
-/*                          1                      a category 1 type         */
-/*                          2                      a category 2 type         */
-/*                          .                      variable number of slots  */
-/*                                                                           */
-/*                      Whitespace is not allowed within the action.         */
-/*                                                                           */
-/*                      Some ICMDs may have several variants. In this case   */
-/*                      the action is build by joining the individual        */
-/*                      actions of the variants with |.                      */
-/*                                                                           */
-/*                                                                           */
-/* CAUTION: Do not use preprocessor directives in this file! They will       */
-/*          confuse the generator.                                           */
-/*                                                                           */
-
-
-/*  0*/ {N("NOP            ") DF_0_TO_0 , CF_NORMAL, 0              /*    (--)                 */},
-/*  1*/ {N("ACONST         ") DF_0_TO_1 , CF_NORMAL, PEI            /*    (--A)                */},
-/*  2*/ {N("CHECKNULL      ") DF_1_TO_1 , CF_NORMAL, PEI            /*    (A--A)               */},
-/*  3*/ {N("ICONST         ") DF_0_TO_1 , CF_NORMAL, 0              /*    (--I)                */},
-/*  4*/ {N("UNDEF4         ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
-/*  5*/ {N("IDIVPOW2       ") DF_1_TO_1 , CF_NORMAL, 0              /* S+ (I--I)               */},
-/*  6*/ {N("LDIVPOW2       ") DF_1_TO_1 , CF_NORMAL, 0              /* S+ (L--L)               */},
-/*  7*/ {N("UNDEF7         ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
-/*  8*/ {N("UNDEF8         ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
-/*  9*/ {N("LCONST         ") DF_0_TO_1 , CF_NORMAL, 0              /*    (--L)                */},
-/* 10*/ {N("LCMPCONST      ") DF_1_TO_1 , CF_NORMAL, 0              /* S+ (L--I)               */},
-/* 11*/ {N("FCONST         ") DF_0_TO_1 , CF_NORMAL, 0              /*    (--F)                */},
-/* 12*/ {N("UNDEF12        ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
-/* 13*/ {N("UNDEF13        ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
-/* 14*/ {N("DCONST         ") DF_0_TO_1 , CF_NORMAL, 0              /*    (--D)                */},
-/* 15*/ {N("COPY           ") DF_COPY   , CF_NORMAL, 0              /* S+ (1--1)               */},
-/* 16*/ {N("MOVE           ") DF_MOVE   , CF_NORMAL, 0              /* S+ (1--1)               */},
-/* 17*/ {N("UNDEF17        ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
-/* 18*/ {N("UNDEF18        ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
-/* 19*/ {N("UNDEF19        ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
-/* 20*/ {N("UNDEF20        ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
-/* 21*/ {N("ILOAD          ") DF_LOAD   , CF_NORMAL, 0              /*    (--I)                */},
-/* 22*/ {N("LLOAD          ") DF_LOAD   , CF_NORMAL, 0              /*    (--L)                */},
-/* 23*/ {N("FLOAD          ") DF_LOAD   , CF_NORMAL, 0              /*    (--F)                */},
-/* 24*/ {N("DLOAD          ") DF_LOAD   , CF_NORMAL, 0              /*    (--D)                */},
-/* 25*/ {N("ALOAD          ") DF_LOAD   , CF_NORMAL, 0              /*    (--A)                */},
-/* 26*/ {N("IADDCONST      ") DF_1_TO_1 , CF_NORMAL, 0              /* S+ (I--I)               */},
-/* 27*/ {N("ISUBCONST      ") DF_1_TO_1 , CF_NORMAL, 0              /* S+ (I--I)               */},
-/* 28*/ {N("IMULCONST      ") DF_1_TO_1 , CF_NORMAL, 0              /* S+ (I--I)               */},
-/* 29*/ {N("IANDCONST      ") DF_1_TO_1 , CF_NORMAL, 0              /* S+ (I--I)               */},
-/* 30*/ {N("IORCONST       ") DF_1_TO_1 , CF_NORMAL, 0              /* S+ (I--I)               */},
-/* 31*/ {N("IXORCONST      ") DF_1_TO_1 , CF_NORMAL, 0              /* S+ (I--I)               */},
-/* 32*/ {N("ISHLCONST      ") DF_1_TO_1 , CF_NORMAL, 0              /* S+ (I--I)               */},
-/* 33*/ {N("ISHRCONST      ") DF_1_TO_1 , CF_NORMAL, 0              /* S+ (I--I)               */},
-/* 34*/ {N("IUSHRCONST     ") DF_1_TO_1 , CF_NORMAL, 0              /* S+ (I--I)               */},
-/* 35*/ {N("IREMPOW2       ") DF_1_TO_1 , CF_NORMAL, 0              /* S+ (I--I)               */},
-/* 36*/ {N("LADDCONST      ") DF_1_TO_1 , CF_NORMAL, 0              /* S+ (L--L)               */},
-/* 37*/ {N("LSUBCONST      ") DF_1_TO_1 , CF_NORMAL, 0              /* S+ (L--L)               */},
-/* 38*/ {N("LMULCONST      ") DF_1_TO_1 , CF_NORMAL, 0              /* S+ (L--L)               */},
-/* 39*/ {N("LANDCONST      ") DF_1_TO_1 , CF_NORMAL, 0              /* S+ (L--L)               */},
-/* 40*/ {N("LORCONST       ") DF_1_TO_1 , CF_NORMAL, 0              /* S+ (L--L)               */},
-/* 41*/ {N("LXORCONST      ") DF_1_TO_1 , CF_NORMAL, 0              /* S+ (L--L)               */},
-/* 42*/ {N("LSHLCONST      ") DF_1_TO_1 , CF_NORMAL, 0              /* S+ (L--L)               */},
-/* 43*/ {N("LSHRCONST      ") DF_1_TO_1 , CF_NORMAL, 0              /* S+ (L--L)               */},
-/* 44*/ {N("LUSHRCONST     ") DF_1_TO_1 , CF_NORMAL, 0              /* S+ (L--L)               */},
-/* 45*/ {N("LREMPOW2       ") DF_1_TO_1 , CF_NORMAL, 0              /* S+ (L--L)               */},
-/* 46*/ {N("IALOAD         ") DF_2_TO_1 , CF_NORMAL, PEI            /*    (AI--I)              */},
-/* 47*/ {N("LALOAD         ") DF_2_TO_1 , CF_NORMAL, PEI            /*    (AI--L)              */},
-/* 48*/ {N("FALOAD         ") DF_2_TO_1 , CF_NORMAL, PEI            /*    (AI--F)              */},
-/* 49*/ {N("DALOAD         ") DF_2_TO_1 , CF_NORMAL, PEI            /*    (AI--D)              */},
-/* 50*/ {N("AALOAD         ") DF_2_TO_1 , CF_NORMAL, PEI            /*    (AI--A)              */},
-/* 51*/ {N("BALOAD         ") DF_2_TO_1 , CF_NORMAL, PEI            /*    (AI--I)              */},
-/* 52*/ {N("CALOAD         ") DF_2_TO_1 , CF_NORMAL, PEI            /*    (AI--I)              */},
-/* 53*/ {N("SALOAD         ") DF_2_TO_1 , CF_NORMAL, PEI            /*    (AI--I)              */},
-/* 54*/ {N("ISTORE         ") DF_STORE  , CF_NORMAL, 0              /*    (I--)                */},
-/* 55*/ {N("LSTORE         ") DF_STORE  , CF_NORMAL, 0              /*    (L--)                */},
-/* 56*/ {N("FSTORE         ") DF_STORE  , CF_NORMAL, 0              /*    (F--)                */},
-/* 57*/ {N("DSTORE         ") DF_STORE  , CF_NORMAL, 0              /*    (D--)                */},
-/* 58*/ {N("ASTORE         ") DF_STORE  , CF_NORMAL, 0              /*    (A--|R--)            */},
-/* 59*/ {N("IF_LEQ         ") DF_1_TO_0 , CF_IF    , 0              /* S+ (L--)                */},
-/* 60*/ {N("IF_LNE         ") DF_1_TO_0 , CF_IF    , 0              /* S+ (L--)                */},
-/* 61*/ {N("IF_LLT         ") DF_1_TO_0 , CF_IF    , 0              /* S+ (L--)                */},
-/* 62*/ {N("IF_LGE         ") DF_1_TO_0 , CF_IF    , 0              /* S+ (L--)                */},
-/* 63*/ {N("IF_LGT         ") DF_1_TO_0 , CF_IF    , 0              /* S+ (L--)                */},
-/* 64*/ {N("IF_LLE         ") DF_1_TO_0 , CF_IF    , 0              /* S+ (L--)                */},
-/* 65*/ {N("IF_LCMPEQ      ") DF_2_TO_0 , CF_IF    , 0              /* S+ (LL--)               */},
-/* 66*/ {N("IF_LCMPNE      ") DF_2_TO_0 , CF_IF    , 0              /* S+ (LL--)               */},
-/* 67*/ {N("IF_LCMPLT      ") DF_2_TO_0 , CF_IF    , 0              /* S+ (LL--)               */},
-/* 68*/ {N("IF_LCMPGE      ") DF_2_TO_0 , CF_IF    , 0              /* S+ (LL--)               */},
-/* 69*/ {N("IF_LCMPGT      ") DF_2_TO_0 , CF_IF    , 0              /* S+ (LL--)               */},
-/* 70*/ {N("IF_LCMPLE      ") DF_2_TO_0 , CF_IF    , 0              /* S+ (LL--)               */},
-/* 71*/ {N("UNDEF71        ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
-/* 72*/ {N("UNDEF72        ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
-/* 73*/ {N("UNDEF73        ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
-/* 74*/ {N("UNDEF74        ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
-/* 75*/ {N("UNDEF75        ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
-/* 76*/ {N("UNDEF76        ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
-/* 77*/ {N("UNDEF77        ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
-/* 78*/ {N("UNDEF78        ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
-/* 79*/ {N("IASTORE        ") DF_3_TO_0 , CF_NORMAL, PEI            /*    (AII--)              */},
-/* 80*/ {N("LASTORE        ") DF_3_TO_0 , CF_NORMAL, PEI            /*    (AIL--)              */},
-/* 81*/ {N("FASTORE        ") DF_3_TO_0 , CF_NORMAL, PEI            /*    (AIF--)              */},
-/* 82*/ {N("DASTORE        ") DF_3_TO_0 , CF_NORMAL, PEI            /*    (AID--)              */},
-/* 83*/ {N("AASTORE        ") DF_3_TO_0 , CF_NORMAL, PEI|CALLS      /*    (AIA--)              */},
-/* 84*/ {N("BASTORE        ") DF_3_TO_0 , CF_NORMAL, PEI            /*    (AII--)              */},
-/* 85*/ {N("CASTORE        ") DF_3_TO_0 , CF_NORMAL, PEI            /*    (AII--)              */},
-/* 86*/ {N("SASTORE        ") DF_3_TO_0 , CF_NORMAL, PEI            /*    (AII--)              */},
-/* 87*/ {N("POP            ") DF_POP    , CF_NORMAL, 0              /*    (1--)                */},
-/* 88*/ {N("POP2           ") DF_POP2   , CF_NORMAL, 0              /*    (11--|2--)           */},
-/* 89*/ {N("DUP            ") DF_DUP    , CF_NORMAL, 0              /* -S (1--11)              */},
-/* 90*/ {N("DUP_X1         ") DF_DUP_X1 , CF_NORMAL, 0              /* -S (11--111)            */},
-/* 91*/ {N("DUP_X2         ") DF_DUP_X2 , CF_NORMAL, 0              /* -S (111--1111|21--121)  */},
-/* 92*/ {N("DUP2           ") DF_DUP2   , CF_NORMAL, 0              /* -S (11--1111|2--22)     */},
-/* 93*/ {N("DUP2_X1        ") DF_DUP2_X1, CF_NORMAL, 0              /* -S (111--11111|12--212) */},
-/* 94*/ {N("DUP2_X2        ") DF_DUP2_X2, CF_NORMAL, 0              /* -S (1111--111111|112--2112|22--222|211--11211) */},
-/* 95*/ {N("SWAP           ") DF_SWAP   , CF_NORMAL, 0              /* -S (11--11)             */},
-/* 96*/ {N("IADD           ") DF_2_TO_1 , CF_NORMAL, 0              /*    (II--I)              */},
-/* 97*/ {N("LADD           ") DF_2_TO_1 , CF_NORMAL, 0              /*    (LL--L)              */},
-/* 98*/ {N("FADD           ") DF_2_TO_1 , CF_NORMAL, 0              /*    (FF--F)              */},
-/* 99*/ {N("DADD           ") DF_2_TO_1 , CF_NORMAL, 0              /*    (DD--D)              */},
-/*100*/ {N("ISUB           ") DF_2_TO_1 , CF_NORMAL, 0              /*    (II--I)              */},
-/*101*/ {N("LSUB           ") DF_2_TO_1 , CF_NORMAL, 0              /*    (LL--L)              */},
-/*102*/ {N("FSUB           ") DF_2_TO_1 , CF_NORMAL, 0              /*    (FF--F)              */},
-/*103*/ {N("DSUB           ") DF_2_TO_1 , CF_NORMAL, 0              /*    (DD--D)              */},
-/*104*/ {N("IMUL           ") DF_2_TO_1 , CF_NORMAL, 0              /*    (II--I)              */},
-/*105*/ {N("LMUL           ") DF_2_TO_1 , CF_NORMAL, 0              /*    (LL--L)              */},
-/*106*/ {N("FMUL           ") DF_2_TO_1 , CF_NORMAL, 0              /*    (FF--F)              */},
-/*107*/ {N("DMUL           ") DF_2_TO_1 , CF_NORMAL, 0              /*    (DD--D)              */},
-/*108*/ {N("IDIV           ") DF_2_TO_1 , CF_NORMAL, PEI|IDIV_CALLS /*    (II--I)              */},
-/*109*/ {N("LDIV           ") DF_2_TO_1 , CF_NORMAL, PEI|LDIV_CALLS /*    (LL--L)              */},
-/*110*/ {N("FDIV           ") DF_2_TO_1 , CF_NORMAL, 0              /*    (FF--F)              */},
-/*111*/ {N("DDIV           ") DF_2_TO_1 , CF_NORMAL, 0              /*    (DD--D)              */},
-/*112*/ {N("IREM           ") DF_2_TO_1 , CF_NORMAL, PEI|IDIV_CALLS /*    (II--I)              */},
-/*113*/ {N("LREM           ") DF_2_TO_1 , CF_NORMAL, PEI|LDIV_CALLS /*    (LL--L)              */},
-/*114*/ {N("FREM           ") DF_2_TO_1 , CF_NORMAL, 0              /*    (FF--F)              */},
-/*115*/ {N("DREM           ") DF_2_TO_1 , CF_NORMAL, 0              /*    (DD--D)              */},
-/*116*/ {N("INEG           ") DF_1_TO_1 , CF_NORMAL, 0              /*    (I--I)               */},
-/*117*/ {N("LNEG           ") DF_1_TO_1 , CF_NORMAL, 0              /*    (L--L)               */},
-/*118*/ {N("FNEG           ") DF_1_TO_1 , CF_NORMAL, 0              /*    (F--F)               */},
-/*119*/ {N("DNEG           ") DF_1_TO_1 , CF_NORMAL, 0              /*    (D--D)               */},
-/*120*/ {N("ISHL           ") DF_2_TO_1 , CF_NORMAL, 0              /*    (II--I)              */},
-/*121*/ {N("LSHL           ") DF_2_TO_1 , CF_NORMAL, 0              /*    (LI--L)              */},
-/*122*/ {N("ISHR           ") DF_2_TO_1 , CF_NORMAL, 0              /*    (II--I)              */},
-/*123*/ {N("LSHR           ") DF_2_TO_1 , CF_NORMAL, 0              /*    (LI--L)              */},
-/*124*/ {N("IUSHR          ") DF_2_TO_1 , CF_NORMAL, 0              /*    (II--I)              */},
-/*125*/ {N("LUSHR          ") DF_2_TO_1 , CF_NORMAL, 0              /*    (LI--L)              */},
-/*126*/ {N("IAND           ") DF_2_TO_1 , CF_NORMAL, 0              /*    (II--I)              */},
-/*127*/ {N("LAND           ") DF_2_TO_1 , CF_NORMAL, 0              /*    (LL--L)              */},
-/*128*/ {N("IOR            ") DF_2_TO_1 , CF_NORMAL, 0              /*    (II--I)              */},
-/*129*/ {N("LOR            ") DF_2_TO_1 , CF_NORMAL, 0              /*    (LL--L)              */},
-/*130*/ {N("IXOR           ") DF_2_TO_1 , CF_NORMAL, 0              /*    (II--I)              */},
-/*131*/ {N("LXOR           ") DF_2_TO_1 , CF_NORMAL, 0              /*    (LL--L)              */},
-/*132*/ {N("IINC           ") DF_IINC   , CF_NORMAL, 0              /*    (--)                 */},
-/*133*/ {N("I2L            ") DF_1_TO_1 , CF_NORMAL, 0              /*    (I--L)               */},
-/*134*/ {N("I2F            ") DF_1_TO_1 , CF_NORMAL, 0              /*    (I--F)               */},
-/*135*/ {N("I2D            ") DF_1_TO_1 , CF_NORMAL, 0              /*    (I--D)               */},
-/*136*/ {N("L2I            ") DF_1_TO_1 , CF_NORMAL, 0              /*    (L--I)               */},
-/*137*/ {N("L2F            ") DF_1_TO_1 , CF_NORMAL, 0              /*    (L--F)               */},
-/*138*/ {N("L2D            ") DF_1_TO_1 , CF_NORMAL, 0              /*    (L--D)               */},
-/*139*/ {N("F2I            ") DF_1_TO_1 , CF_NORMAL, 0              /*    (F--I)               */},
-/*140*/ {N("F2L            ") DF_1_TO_1 , CF_NORMAL, 0              /*    (F--L)               */},
-/*141*/ {N("F2D            ") DF_1_TO_1 , CF_NORMAL, 0              /*    (F--D)               */},
-/*142*/ {N("D2I            ") DF_1_TO_1 , CF_NORMAL, 0              /*    (D--I)               */},
-/*143*/ {N("D2L            ") DF_1_TO_1 , CF_NORMAL, 0              /*    (D--L)               */},
-/*144*/ {N("D2F            ") DF_1_TO_1 , CF_NORMAL, 0              /*    (D--F)               */},
-/*145*/ {N("INT2BYTE       ") DF_1_TO_1 , CF_NORMAL, 0              /*    (I--I)               */},
-/*146*/ {N("INT2CHAR       ") DF_1_TO_1 , CF_NORMAL, 0              /*    (I--I)               */},
-/*147*/ {N("INT2SHORT      ") DF_1_TO_1 , CF_NORMAL, 0              /*    (I--I)               */},
-/*148*/ {N("LCMP           ") DF_2_TO_1 , CF_NORMAL, 0              /*    (LL--I)              */},
-/*149*/ {N("FCMPL          ") DF_2_TO_1 , CF_NORMAL, 0              /*    (FF--I)              */},
-/*150*/ {N("FCMPG          ") DF_2_TO_1 , CF_NORMAL, 0              /*    (FF--I)              */},
-/*151*/ {N("DCMPL          ") DF_2_TO_1 , CF_NORMAL, 0              /*    (DD--I)              */},
-/*152*/ {N("DCMPG          ") DF_2_TO_1 , CF_NORMAL, 0              /*    (DD--I)              */},
-/*153*/ {N("IFEQ           ") DF_1_TO_0 , CF_IF    , 0              /*    (I--)                */},
-/*154*/ {N("IFNE           ") DF_1_TO_0 , CF_IF    , 0              /*    (I--)                */},
-/*155*/ {N("IFLT           ") DF_1_TO_0 , CF_IF    , 0              /*    (I--)                */},
-/*156*/ {N("IFGE           ") DF_1_TO_0 , CF_IF    , 0              /*    (I--)                */},
-/*157*/ {N("IFGT           ") DF_1_TO_0 , CF_IF    , 0              /*    (I--)                */},
-/*158*/ {N("IFLE           ") DF_1_TO_0 , CF_IF    , 0              /*    (I--)                */},
-/*159*/ {N("IF_ICMPEQ      ") DF_2_TO_0 , CF_IF    , 0              /*    (II--)               */},
-/*160*/ {N("IF_ICMPNE      ") DF_2_TO_0 , CF_IF    , 0              /*    (II--)               */},
-/*161*/ {N("IF_ICMPLT      ") DF_2_TO_0 , CF_IF    , 0              /*    (II--)               */},
-/*162*/ {N("IF_ICMPGE      ") DF_2_TO_0 , CF_IF    , 0              /*    (II--)               */},
-/*163*/ {N("IF_ICMPGT      ") DF_2_TO_0 , CF_IF    , 0              /*    (II--)               */},
-/*164*/ {N("IF_ICMPLE      ") DF_2_TO_0 , CF_IF    , 0              /*    (II--)               */},
-/*165*/ {N("IF_ACMPEQ      ") DF_2_TO_0 , CF_IF    , 0              /*    (AA--)               */},
-/*166*/ {N("IF_ACMPNE      ") DF_2_TO_0 , CF_IF    , 0              /*    (AA--)               */},
-/*167*/ {N("GOTO           ") DF_0_TO_0 , CF_GOTO  , 0              /*    (--)                 */},
-/*168*/ {N("JSR            ") DF_0_TO_1 , CF_JSR   , 0              /*    (--R)                */},
-/*169*/ {N("RET            ") DF_0_TO_0 , CF_RET   , 0              /*    (--)                 */},
-/*170*/ {N("TABLESWITCH    ") DF_1_TO_0 , CF_TABLE , 0              /*    (I--)                */},
-/*171*/ {N("LOOKUPSWITCH   ") DF_1_TO_0 , CF_LOOKUP, 0              /*    (I--)                */},
-/*172*/ {N("IRETURN        ") DF_1_TO_0 , CF_END   , 0              /*    (I--)                */},
-/*173*/ {N("LRETURN        ") DF_1_TO_0 , CF_END   , 0              /*    (L--)                */},
-/*174*/ {N("FRETURN        ") DF_1_TO_0 , CF_END   , 0              /*    (F--)                */},
-/*175*/ {N("DRETURN        ") DF_1_TO_0 , CF_END   , 0              /*    (D--)                */},
-/*176*/ {N("ARETURN        ") DF_1_TO_0 , CF_END   , PEI            /*    (A--)                */},
-/*177*/ {N("RETURN         ") DF_0_TO_0 , CF_END   , 0              /*    (--)                 */},
-/*178*/ {N("GETSTATIC      ") DF_0_TO_1 , CF_NORMAL, PEI            /*    (--1|--2)            */},
-/*179*/ {N("PUTSTATIC      ") DF_1_TO_0 , CF_NORMAL, PEI            /*    (1--|2--)            */},
-/*180*/ {N("GETFIELD       ") DF_1_TO_1 , CF_NORMAL, PEI            /*    (A--1|A--2)          */},
-/*181*/ {N("PUTFIELD       ") DF_2_TO_0 , CF_NORMAL, PEI            /*    (A1--|A2--)          */},
-/*182*/ {N("INVOKEVIRTUAL  ") DF_INVOKE , CF_NORMAL, PEI|CALLS      /*    (.--1|.--2|.--)      */},
-/*183*/ {N("INVOKESPECIAL  ") DF_INVOKE , CF_NORMAL, PEI|CALLS      /*    (.--1|.--2|.--)      */},
-/*184*/ {N("INVOKESTATIC   ") DF_INVOKE , CF_NORMAL, PEI|CALLS      /*    (.--1|.--2|.--)      */},
-/*185*/ {N("INVOKEINTERFACE") DF_INVOKE , CF_NORMAL, PEI|CALLS      /*    (.--1|.--2|.--)      */},
-/*186*/ {N("UNDEF186       ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
-/*187*/ {N("NEW            ") DF_0_TO_1 , CF_NORMAL, PEI            /* -- (--A)                */},
-/*188*/ {N("NEWARRAY       ") DF_0_TO_1 , CF_NORMAL, PEI            /* -- (--A)                */},
-/*189*/ {N("ANEWARRAY      ") DF_0_TO_1 , CF_NORMAL, PEI            /* -- (--A)                */},
-/*190*/ {N("ARRAYLENGTH    ") DF_1_TO_1 , CF_NORMAL, PEI            /*    (A--I)               */},
-/*191*/ {N("ATHROW         ") DF_1_TO_0 , CF_END   , PEI            /*    (A--)                */},
-/*192*/ {N("CHECKCAST      ") DF_1_TO_1 , CF_NORMAL, PEI|CALLS      /*    (A--A)               */},
-/*193*/ {N("INSTANCEOF     ") DF_1_TO_1 , CF_NORMAL, PEI|CALLS      /*    (A--I)               */},
-/*194*/ {N("MONITORENTER   ") DF_1_TO_0 , CF_NORMAL, PEI|CALLS      /* -- (A--)                */},
-/*195*/ {N("MONITOREXIT    ") DF_1_TO_0 , CF_NORMAL, PEI|CALLS      /* -- (A--)                */},
-/*196*/ {N("UNDEF196       ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
-/*197*/ {N("MULTIANEWARRAY ") DF_N_TO_1 , CF_NORMAL, PEI|CALLS      /*    (.--A)               */},
-/*198*/ {N("IFNULL         ") DF_1_TO_0 , CF_IF    , 0              /*    (A--)                */},
-/*199*/ {N("IFNONNULL      ") DF_1_TO_0 , CF_IF    , 0              /*    (A--)                */},
-/*200*/ {N("UNDEF200       ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
-/*201*/ {N("UNDEF201       ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
-/*202*/ {N("UNDEF202       ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
-/*203*/ {N("UNDEF203       ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
-/*204*/ {N("IASTORECONST   ") DF_2_TO_0 , CF_NORMAL, PEI            /* S+ (AI--)               */},
-/*205*/ {N("LASTORECONST   ") DF_2_TO_0 , CF_NORMAL, PEI            /* S+ (AI--)               */},
-/*206*/ {N("FASTORECONST   ") DF_2_TO_0 , CF_NORMAL, PEI            /* S+ (AI--)               */},
-/*207*/ {N("DASTORECONST   ") DF_2_TO_0 , CF_NORMAL, PEI            /* S+ (AI--)               */},
-/*208*/ {N("AASTORECONST   ") DF_2_TO_0 , CF_NORMAL, PEI            /* S+ (AI--)               */},
-/*209*/ {N("BASTORECONST   ") DF_2_TO_0 , CF_NORMAL, PEI            /* S+ (AI--)               */},
-/*210*/ {N("CASTORECONST   ") DF_2_TO_0 , CF_NORMAL, PEI            /* S+ (AI--)               */},
-/*211*/ {N("SASTORECONST   ") DF_2_TO_0 , CF_NORMAL, PEI            /* S+ (AI--)               */},
-/*212*/ {N("PUTSTATICCONST ") DF_0_TO_0 , CF_NORMAL, PEI            /* S+ (--)                 */},
-/*213*/ {N("PUTFIELDCONST  ") DF_1_TO_0 , CF_NORMAL, PEI            /* S+ (A--)                */},
-/*214*/ {N("IMULPOW2       ") DF_1_TO_1 , CF_NORMAL, 0              /* S+ (I--I)               */},
-/*215*/ {N("LMULPOW2       ") DF_1_TO_1 , CF_NORMAL, 0              /* S+ (L--L)               */},
-/*216*/ {N("IF_FCMPEQ      ") DF_0_TO_0 , CF_IF    , 0              /* -- ()                   */},
-/*217*/ {N("IF_FCMPNE      ") DF_0_TO_0 , CF_IF    , 0              /* -- ()                   */},
-/*218*/ {N("IF_FCMPL_LT    ") DF_0_TO_0 , CF_IF    , 0              /* -- ()                   */},
-/*219*/ {N("IF_FCMPL_GE    ") DF_0_TO_0 , CF_IF    , 0              /* -- ()                   */},
-/*220*/ {N("IF_FCMPL_GT    ") DF_0_TO_0 , CF_IF    , 0              /* -- ()                   */},
-/*221*/ {N("IF_FCMPL_LE    ") DF_0_TO_0 , CF_IF    , 0              /* -- ()                   */},
-/*222*/ {N("IF_FCMPG_LT    ") DF_0_TO_0 , CF_IF    , 0              /* -- ()                   */},
-/*223*/ {N("IF_FCMPG_GE    ") DF_0_TO_0 , CF_IF    , 0              /* -- ()                   */},
-/*224*/ {N("IF_FCMPG_GT    ") DF_0_TO_0 , CF_IF    , 0              /* -- ()                   */},
-/*225*/ {N("IF_FCMPG_LE    ") DF_0_TO_0 , CF_IF    , 0              /* -- ()                   */},
-/*226*/ {N("IF_DCMPEQ      ") DF_0_TO_0 , CF_IF    , 0              /* -- ()                   */},
-/*227*/ {N("IF_DCMPNE      ") DF_0_TO_0 , CF_IF    , 0              /* -- ()                   */},
-/*228*/ {N("IF_DCMPL_LT    ") DF_0_TO_0 , CF_IF    , 0              /* -- ()                   */},
-/*229*/ {N("IF_DCMPL_GE    ") DF_0_TO_0 , CF_IF    , 0              /* -- ()                   */},
-/*230*/ {N("IF_DCMPL_GT    ") DF_0_TO_0 , CF_IF    , 0              /* -- ()                   */},
-/*231*/ {N("IF_DCMPL_LE    ") DF_0_TO_0 , CF_IF    , 0              /* -- ()                   */},
-/*232*/ {N("IF_DCMPG_LT    ") DF_0_TO_0 , CF_IF    , 0              /* -- ()                   */},
-/*233*/ {N("IF_DCMPG_GE    ") DF_0_TO_0 , CF_IF    , 0              /* -- ()                   */},
-/*234*/ {N("IF_DCMPG_GT    ") DF_0_TO_0 , CF_IF    , 0              /* -- ()                   */},
-/*235*/ {N("IF_DCMPG_LE    ") DF_0_TO_0 , CF_IF    , 0              /* -- ()                   */},
-/*236*/ {N("UNDEF236       ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
-/*237*/ {N("UNDEF237       ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
-/*238*/ {N("UNDEF238       ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
-/*239*/ {N("UNDEF239       ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
-/*240*/ {N("UNDEF240       ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
-/*241*/ {N("UNDEF241       ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
-/*242*/ {N("UNDEF242       ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
-/*243*/ {N("UNDEF243       ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
-/*244*/ {N("UNDEF244       ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
-/*245*/ {N("UNDEF245       ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
-/*246*/ {N("UNDEF246       ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
-/*247*/ {N("UNDEF247       ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
-/*248*/ {N("UNDEF248       ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
-/*249*/ {N("GETEXCEPTION   ") DF_0_TO_1 , CF_NORMAL, 0              /* -- ()                   */},
-/*250*/ {N("PHI            ") DF_N_TO_1 , CF_NORMAL, 0              /* -- ()                   */},
-/*251*/ {N("INLINE_START   ") DF_0_TO_0 , CF_NORMAL, 0              /* S+ (--)                 */},
-/*252*/ {N("INLINE_END     ") DF_0_TO_0 , CF_NORMAL, 0              /* S+ (--)                 */},
-/*253*/ {N("INLINE_BODY    ") DF_0_TO_0 , CF_NORMAL, 0              /* S+ (--)                 */},
-/*254*/ {N("UNDEF254       ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
-/*255*/ {N("BUILTIN        ") DF_BUILTIN, CF_NORMAL, PEI|CALLS      /*    (.--1|.--2|.--)      */}
-
index d5108a6dfce3326d72003f8bdf0315e9aff50651..f0e71754492bf79e17bf561a1b128d77f7c7ac8f 100644 (file)
 
 #include "mm/memory.h"
 
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
+#include "threads/mutex.hpp"
 #include "threads/thread.hpp"
 
 #include "toolbox/logging.h"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/class.h"
 #include "vm/global.h"
 #include "vm/initialize.h"
 #include "vm/options.h"
 #include "vm/statistics.h"
 
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
 #include "vm/jit/parse.h"
 #include "vm/jit/reg.h"
-#include "vm/jit/show.h"
+#include "vm/jit/show.hpp"
 #include "vm/jit/stack.h"
 
 #include "vm/jit/inline/inline.h"
@@ -337,7 +338,7 @@ static bool inline_jit_compile(inline_node *iln)
 
        /* enter a monitor on the method */
 
-       LOCK_MONITOR_ENTER(m);
+       Mutex_lock(m->mutex);
 
        /* allocate jitdata structure and fill it */
 
@@ -380,7 +381,7 @@ static bool inline_jit_compile(inline_node *iln)
 
        /* leave the monitor */
 
-       LOCK_MONITOR_EXIT(m);
+       Mutex_unlock(m->mutex);
 
        return r;
 }
@@ -2155,9 +2156,6 @@ static bool inline_transform(inline_node *iln, jitdata *jd)
        /* we need bigger free memory stacks (XXX these should not be allocated in reg_setup) */
 
        n_jd->rd->freemem = DMNEW(s4, iln->ctx->maxinoutdepth + 1000) /* XXX max vars/block */;
-#if defined(HAS_4BYTE_STACKSLOT)
-       n_jd->rd->freemem_2 = DMNEW(s4, iln->ctx->maxinoutdepth + 1000) /* XXX max vars/block */;
-#endif
 
 #if defined(ENABLE_INLINING_DEBUG) || !defined(NDEBUG)
        if (   (n_jd->instructioncount >= opt_InlineMinSize)
index cdd41ee4daeeac32ee13b8396d09673fdbb5111b..629f649a9dca2a570603b0cefb8ede76fdc63a2c 100644 (file)
@@ -1,9 +1,7 @@
 /* src/vm/jit/inline/inline.h - code inliner
 
-   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
-   C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
-   E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
-   J. Wenninger, Institut f. Computersprachen - TU Wien
+   Copyright (C) 1996-2005, 2006, 2007, 2008
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
 
 
 #include "config.h"
 
-#include "vm/global.h"
+#include <stdbool.h>
 
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
 
 
 /* function prototypes ********************************************************/
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 bool inline_inline(jitdata *jd);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* _INLINE_H */
 
 /*
index 35cec22935251ea7eb093af0d98f2c89cfc2ee9e..a81b6b0733c1c090ecbfed2a5251aa975408fc75 100644 (file)
 
 #include "threads/thread.hpp"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/class.h"
 #include "vm/linker.h"
-#include "vm/loader.h"
+#include "vm/loader.hpp"
 #include "vm/options.h"
 
 #include "vm/jit/asmpart.h"
index ec35739dab3dc1bbe9d7130749748ed4789b5586..f404c8d5ea8ee7155025aa0d3d29a3bf3af3380f 100644 (file)
@@ -45,9 +45,9 @@
 
 #include "mm/memory.h"
 
-#include "native/native.h"
+#include "native/native.hpp"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/class.h"
 #include "vm/exceptions.hpp"
 #include "vm/global.h"
@@ -55,9 +55,9 @@
 #include "vm/vm.hpp"
 
 #include "vm/jit/asmpart.h"
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/codegen-common.hpp"
 #include "vm/jit/dseg.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
 #include "vm/jit/parse.h"
 #include "vm/jit/patcher.h"
 #include "vm/jit/stack.h"
index dcf7d9e44cc7b3b73b62956c50f13359e9cd3158..78f75df0204b50835800cfbf1058069c7e1998d5 100644 (file)
@@ -38,7 +38,7 @@
 
 #include "mm/memory.h"
 
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
 
 #include "toolbox/hashtable.h"
 #include "toolbox/logging.h"
index e3b2c4772b4f0f2428137d8664309fff5a5e7281..a09239243c2e1b46069a6a370a0cfcefe7d92e5e 100644 (file)
@@ -41,8 +41,8 @@
 
 #include "threads/thread.hpp"
 
-#include "vm/builtin.h"
-#include "vm/loader.h"
+#include "vm/jit/builtin.hpp"
+#include "vm/loader.hpp"
 #include "vm/options.h"
 
 #include "vm/jit/methodheader.h"
index 366f1d9cce9f6d9760e3ec0e596f6f0fd947213c..8b1e0da6e968e89ebc41d970665255c569674d2e 100644 (file)
@@ -51,7 +51,7 @@ typedef s4 Cell;
 #include "vm/references.h"
 #include "vm/resolve.h"
 
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/codegen-common.hpp"
 
 
 typedef void *Label;
index e51fb76c47a14ec356e05132cae19183ee5b438f..191c562c2e5c64dc77cf5cd16011fd82ab84304e 100644 (file)
 
 #include "mm/memory.h"
 
-#include "native/native.h"
+#include "native/native.hpp"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/class.h"
-#include "vm/field.h"
+#include "vm/field.hpp"
 #include "vm/initialize.h"
 #include "vm/options.h"
 #include "vm/references.h"
index 4417c43b675053e01d9c1cf9d80d85d186b95a33..ecfdab36526bc077bc0845b9d761a55b17e1111c 100644 (file)
@@ -1,6 +1,6 @@
 ## src/vm/jit/ir/Makefile.am
 ##
-## Copyright (C) 2007
+## Copyright (C) 2007, 2008
 ## CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 ##
 ## This file is part of CACAO.
@@ -20,7 +20,6 @@
 ## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 ## 02110-1301, USA.
 
-## Process this file with automake to produce Makefile.in
 
 AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/src/vm/jit -I$(top_srcdir)/src/vm/jit/$(ARCH_DIR) -I$(top_srcdir)/src/vm/jit/$(ARCH_DIR)/$(OS_DIR)
 
@@ -31,7 +30,12 @@ noinst_LTLIBRARIES = \
 
 libir_la_SOURCES = \
        bytecode.c \
-       bytecode.h
+       bytecode.h \
+       icmd.cpp \
+       icmd.hpp \
+       icmdtable.inc \
+       instruction.cpp \
+       instruction.hpp
 
 
 ## Local variables:
diff --git a/src/vm/jit/ir/icmd.cpp b/src/vm/jit/ir/icmd.cpp
new file mode 100644 (file)
index 0000000..d0c5057
--- /dev/null
@@ -0,0 +1,79 @@
+/* src/vm/jit/ir/icmd.cpp - Intermediate Commands
+
+   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/jit/ir/icmd.hpp"
+
+
+/* the ICMD table ************************************************************/
+
+#if !defined(NDEBUG)
+#define N(name)  name,
+#else
+#define N(name)
+#endif
+
+/* abbreviations for flags */
+
+#define PEI     ICMDTABLE_PEI
+#define CALLS   ICMDTABLE_CALLS
+
+/* some machine dependent values */
+
+#if SUPPORT_DIVISION
+#define IDIV_CALLS  0
+#else
+#define IDIV_CALLS  ICMDTABLE_CALLS
+#endif
+
+#if (SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
+#define LDIV_CALLS  0
+#else
+#define LDIV_CALLS  ICMDTABLE_CALLS
+#endif
+
+/* include the actual table */
+
+icmdtable_entry_t icmd_table[256] = {
+#include "vm/jit/ir/icmdtable.inc"
+};
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
diff --git a/src/vm/jit/ir/icmd.hpp b/src/vm/jit/ir/icmd.hpp
new file mode 100644 (file)
index 0000000..34557be
--- /dev/null
@@ -0,0 +1,418 @@
+/* src/vm/jit/ir/icmd.hpp - Intermediate Commands
+
+   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 _ICMD_HPP
+#define _ICMD_HPP
+
+#include "config.h"
+
+#include <stdint.h>
+
+#include "vm/jit/ir/bytecode.h"
+
+
+// JavaVM operation codes (sorted).
+enum {
+       ICMD_NOP               = BC_nop,
+
+       ICMD_ACONST            = BC_aconst_null,
+
+       ICMD_CHECKNULL         = 2,
+
+       ICMD_ICONST            = BC_iconst_0,
+
+       /* 3 */
+       /* 4 */
+
+       ICMD_IDIVPOW2          = 5,
+       ICMD_LDIVPOW2          = 6,
+
+       /* 7 */
+       /* 8 */
+
+       ICMD_LCONST            = BC_lconst_0,
+
+       ICMD_LCMPCONST         = 10,
+
+       ICMD_FCONST            = BC_fconst_0,
+
+       /* 12 */
+       /* 13 */
+
+       ICMD_DCONST            = BC_dconst_0,
+
+       ICMD_COPY              = 15,
+       ICMD_MOVE              = 16,
+
+       /* 17 */
+       /* 18 */
+       /* 19 */
+       /* 20 */
+
+       /* Order of LOAD instructions must be equal to order of TYPE_*
+          defines. */
+
+       ICMD_ILOAD            = BC_iload,
+       ICMD_LLOAD            = BC_lload,
+       ICMD_FLOAD            = BC_fload,
+       ICMD_DLOAD            = BC_dload,
+       ICMD_ALOAD            = BC_aload,
+
+       ICMD_IADDCONST        = 26,
+       ICMD_ISUBCONST        = 27,
+       ICMD_IMULCONST        = 28,
+       ICMD_IANDCONST        = 29,
+       ICMD_IORCONST         = 30,
+       ICMD_IXORCONST        = 31,
+
+       ICMD_ISHLCONST        = 32,
+       ICMD_ISHRCONST        = 33,
+       ICMD_IUSHRCONST       = 34,
+
+       ICMD_IREMPOW2         = 35,
+
+       ICMD_LADDCONST        = 36,
+       ICMD_LSUBCONST        = 37,
+       ICMD_LMULCONST        = 38,
+       ICMD_LANDCONST        = 39,
+       ICMD_LORCONST         = 40,
+       ICMD_LXORCONST        = 41,
+
+       ICMD_LSHLCONST        = 42,
+       ICMD_LSHRCONST        = 43,
+       ICMD_LUSHRCONST       = 44,
+
+       ICMD_LREMPOW2         = 45,
+
+       ICMD_IALOAD           = BC_iaload,
+       ICMD_LALOAD           = BC_laload,
+       ICMD_FALOAD           = BC_faload,
+       ICMD_DALOAD           = BC_daload,
+       ICMD_AALOAD           = BC_aaload,
+       ICMD_BALOAD           = BC_baload,
+       ICMD_CALOAD           = BC_caload,
+       ICMD_SALOAD           = BC_saload,
+
+       /* Order of STORE instructions must be equal to order of TYPE_*
+          defines. */
+
+       ICMD_ISTORE           = BC_istore,
+       ICMD_LSTORE           = BC_lstore,
+       ICMD_FSTORE           = BC_fstore,
+       ICMD_DSTORE           = BC_dstore,
+       ICMD_ASTORE           = BC_astore,
+
+       ICMD_IF_LEQ           = 59,
+       ICMD_IF_LNE           = 60,
+       ICMD_IF_LLT           = 61,
+       ICMD_IF_LGE           = 62,
+       ICMD_IF_LGT           = 63,
+       ICMD_IF_LLE           = 64,
+
+       ICMD_IF_LCMPEQ        = 65,
+       ICMD_IF_LCMPNE        = 66,
+       ICMD_IF_LCMPLT        = 67,
+       ICMD_IF_LCMPGE        = 68,
+       ICMD_IF_LCMPGT        = 69,
+       ICMD_IF_LCMPLE        = 70,
+
+       /* 71 */
+       /* 72 */
+       /* 73 */
+       /* 74 */
+       /* 75 */
+       /* 76 */
+       /* 77 */
+       /* 78 */
+
+       ICMD_IASTORE          = BC_iastore,
+       ICMD_LASTORE          = BC_lastore,
+       ICMD_FASTORE          = BC_fastore,
+       ICMD_DASTORE          = BC_dastore,
+       ICMD_AASTORE          = BC_aastore,
+       ICMD_BASTORE          = BC_bastore,
+       ICMD_CASTORE          = BC_castore,
+       ICMD_SASTORE          = BC_sastore,
+
+       ICMD_POP              = BC_pop,
+       ICMD_POP2             = BC_pop2,
+       ICMD_DUP              = BC_dup,
+       ICMD_DUP_X1           = BC_dup_x1,
+       ICMD_DUP_X2           = BC_dup_x2,
+       ICMD_DUP2             = BC_dup2,
+       ICMD_DUP2_X1          = BC_dup2_x1,
+       ICMD_DUP2_X2          = BC_dup2_x2,
+       ICMD_SWAP             = BC_swap,
+
+       ICMD_IADD             = BC_iadd,
+       ICMD_LADD             = BC_ladd,
+       ICMD_FADD             = BC_fadd,
+       ICMD_DADD             = BC_dadd,
+
+       ICMD_ISUB             = BC_isub,
+       ICMD_LSUB             = BC_lsub,
+       ICMD_FSUB             = BC_fsub,
+       ICMD_DSUB             = BC_dsub,
+
+       ICMD_IMUL             = BC_imul,
+       ICMD_LMUL             = BC_lmul,
+       ICMD_FMUL             = BC_fmul,
+       ICMD_DMUL             = BC_dmul,
+
+       ICMD_IDIV             = BC_idiv,
+       ICMD_LDIV             = BC_ldiv,
+       ICMD_FDIV             = BC_fdiv,
+       ICMD_DDIV             = BC_ddiv,
+
+       ICMD_IREM             = BC_irem,
+       ICMD_LREM             = BC_lrem,
+       ICMD_FREM             = BC_frem,
+       ICMD_DREM             = BC_drem,
+
+       ICMD_INEG             = BC_ineg,
+       ICMD_LNEG             = BC_lneg,
+       ICMD_FNEG             = BC_fneg,
+       ICMD_DNEG             = BC_dneg,
+
+       ICMD_ISHL             = BC_ishl,
+       ICMD_LSHL             = BC_lshl,
+       ICMD_ISHR             = BC_ishr,
+       ICMD_LSHR             = BC_lshr,
+       ICMD_IUSHR            = BC_iushr,
+       ICMD_LUSHR            = BC_lushr,
+
+       ICMD_IAND             = BC_iand,
+       ICMD_LAND             = BC_land,
+       ICMD_IOR              = BC_ior,
+       ICMD_LOR              = BC_lor,
+       ICMD_IXOR             = BC_ixor,
+       ICMD_LXOR             = BC_lxor,
+
+       ICMD_IINC             = BC_iinc,
+
+       ICMD_I2L              = BC_i2l,
+       ICMD_I2F              = BC_i2f,
+       ICMD_I2D              = BC_i2d,
+       ICMD_L2I              = BC_l2i,
+       ICMD_L2F              = BC_l2f,
+       ICMD_L2D              = BC_l2d,
+       ICMD_F2I              = BC_f2i,
+       ICMD_F2L              = BC_f2l,
+       ICMD_F2D              = BC_f2d,
+       ICMD_D2I              = BC_d2i,
+       ICMD_D2L              = BC_d2l,
+       ICMD_D2F              = BC_d2f,
+
+       ICMD_INT2BYTE         = BC_int2byte,
+       ICMD_INT2CHAR         = BC_int2char,
+       ICMD_INT2SHORT        = BC_int2short,
+
+       ICMD_LCMP             = BC_lcmp,
+       ICMD_FCMPL            = BC_fcmpl,
+       ICMD_FCMPG            = BC_fcmpg,
+       ICMD_DCMPL            = BC_dcmpl,
+       ICMD_DCMPG            = BC_dcmpg,
+
+       ICMD_IFEQ             = BC_ifeq,
+       ICMD_IFNE             = BC_ifne,
+       ICMD_IFLT             = BC_iflt,
+       ICMD_IFGE             = BC_ifge,
+       ICMD_IFGT             = BC_ifgt,
+       ICMD_IFLE             = BC_ifle,
+
+       ICMD_IF_ICMPEQ        = BC_if_icmpeq,
+       ICMD_IF_ICMPNE        = BC_if_icmpne,
+       ICMD_IF_ICMPLT        = BC_if_icmplt,
+       ICMD_IF_ICMPGE        = BC_if_icmpge,
+       ICMD_IF_ICMPGT        = BC_if_icmpgt,
+       ICMD_IF_ICMPLE        = BC_if_icmple,
+       ICMD_IF_ACMPEQ        = BC_if_acmpeq,
+       ICMD_IF_ACMPNE        = BC_if_acmpne,
+
+       ICMD_GOTO             = BC_goto,
+       ICMD_JSR              = BC_jsr,
+       ICMD_RET              = BC_ret,
+
+       ICMD_TABLESWITCH      = BC_tableswitch,
+       ICMD_LOOKUPSWITCH     = BC_lookupswitch,
+
+       ICMD_IRETURN          = BC_ireturn,
+       ICMD_LRETURN          = BC_lreturn,
+       ICMD_FRETURN          = BC_freturn,
+       ICMD_DRETURN          = BC_dreturn,
+       ICMD_ARETURN          = BC_areturn,
+       ICMD_RETURN           = BC_return,
+
+       ICMD_GETSTATIC        = BC_getstatic,
+       ICMD_PUTSTATIC        = BC_putstatic,
+       ICMD_GETFIELD         = BC_getfield,
+       ICMD_PUTFIELD         = BC_putfield,
+
+       ICMD_INVOKEVIRTUAL    = BC_invokevirtual,
+       ICMD_INVOKESPECIAL    = BC_invokespecial,
+       ICMD_INVOKESTATIC     = BC_invokestatic,
+       ICMD_INVOKEINTERFACE  = BC_invokeinterface,
+
+       /* 186 */
+
+       ICMD_NEW              = BC_new,
+       ICMD_NEWARRAY         = BC_newarray,
+       ICMD_ANEWARRAY        = BC_anewarray,
+
+       ICMD_ARRAYLENGTH      = BC_arraylength,
+
+       ICMD_ATHROW           = BC_athrow,
+
+       ICMD_CHECKCAST        = BC_checkcast,
+       ICMD_INSTANCEOF       = BC_instanceof,
+
+       ICMD_MONITORENTER     = BC_monitorenter,
+       ICMD_MONITOREXIT      = BC_monitorexit,
+
+       /* 196 */
+
+       ICMD_MULTIANEWARRAY   = BC_multianewarray,
+
+       ICMD_IFNULL           = BC_ifnull,
+       ICMD_IFNONNULL        = BC_ifnonnull,
+
+       /* 200 */
+       /* 201 */
+       /* 202 */
+
+       ICMD_IASTORECONST     = 204,
+       ICMD_LASTORECONST     = 205,
+       ICMD_FASTORECONST     = 206,
+       ICMD_DASTORECONST     = 207,
+       ICMD_AASTORECONST     = 208,
+       ICMD_BASTORECONST     = 209,
+       ICMD_CASTORECONST     = 210,
+       ICMD_SASTORECONST     = 211,
+
+       ICMD_PUTSTATICCONST   = 212,
+       ICMD_PUTFIELDCONST    = 213,
+
+       ICMD_IMULPOW2         = 214,
+       ICMD_LMULPOW2         = 215,
+
+       ICMD_GETEXCEPTION     = 249,
+       ICMD_PHI              = 250,
+
+       ICMD_INLINE_START     = 251,        /* instruction before inlined method  */
+       ICMD_INLINE_END       = 252,        /* instruction after inlined method   */
+       ICMD_INLINE_BODY      = 253,        /* start of inlined body              */
+
+       ICMD_BUILTIN          = 255         /* internal opcode                    */
+};
+
+
+/* data-flow constants for the ICMD table ************************************/
+
+#define DF_0_TO_0      0
+#define DF_1_TO_0      1
+#define DF_2_TO_0      2
+#define DF_3_TO_0      3
+
+#define DF_DST_BASE    4      /* from this value on, iptr->dst is a variable */
+
+#define DF_0_TO_1      (DF_DST_BASE + 0)
+#define DF_1_TO_1      (DF_DST_BASE + 1)
+#define DF_2_TO_1      (DF_DST_BASE + 2)
+#define DF_3_TO_1      (DF_DST_BASE + 3)
+#define DF_N_TO_1      (DF_DST_BASE + 4)
+
+#define DF_INVOKE      (DF_DST_BASE + 5)
+#define DF_BUILTIN     (DF_DST_BASE + 6)
+
+#define DF_COPY        (DF_DST_BASE + 7)
+#define DF_MOVE        (DF_DST_BASE + 8)
+
+#define DF_DUP         -1
+#define DF_DUP_X1      -1
+#define DF_DUP_X2      -1
+#define DF_DUP2        -1
+#define DF_DUP2_X1     -1
+#define DF_DUP2_X2     -1
+#define DF_SWAP        -1
+
+/* special data-flow recognized by verify/generate.pl: */
+#define DF_LOAD        DF_COPY
+#define DF_STORE       DF_MOVE
+#define DF_IINC        DF_1_TO_1
+#define DF_POP         DF_1_TO_0
+#define DF_POP2        DF_2_TO_0
+
+
+// Control-flow constants for the ICMD table.
+#define CF_NORMAL      0
+#define CF_IF          1
+
+#define CF_END_BASE    2  /* from here on, they mark the end of a superblock */
+
+#define CF_END         (CF_END_BASE + 0)
+#define CF_GOTO        (CF_END_BASE + 1)
+#define CF_TABLE       (CF_END_BASE + 2)
+#define CF_LOOKUP      (CF_END_BASE + 3)
+#define CF_JSR         (CF_END_BASE + 4)
+#define CF_RET         (CF_END_BASE + 5)
+
+
+// Flag constants for the ICMD table.
+#define ICMDTABLE_PEI    0x0001               /* ICMD may throw an exception */
+#define ICMDTABLE_CALLS  0x0002     /* needs registers to be saved, may call */
+
+
+// ICMD table entry.
+typedef struct icmdtable_entry_t icmdtable_entry_t;
+
+struct icmdtable_entry_t {
+#if !defined(NDEBUG)
+       const char* name;                           /* name, without ICMD_ prefix */
+#endif
+       int32_t dataflow;                            /* a DF_ constant, see above */
+       int32_t controlflow;                         /* a CF_ constant, see above */
+       int32_t flags;                       /* a combination of ICMDTABLE_ flags */
+};
+
+
+// The ICMD table.
+extern icmdtable_entry_t icmd_table[256];
+
+#endif // _ICMD_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:
+ */
diff --git a/src/vm/jit/ir/icmdtable.inc b/src/vm/jit/ir/icmdtable.inc
new file mode 100644 (file)
index 0000000..4b0639c
--- /dev/null
@@ -0,0 +1,310 @@
+/*** The ICMD Table ***/
+
+/* IMPORTANT: This file must be in a fixed format, as it is both included in */
+/* src/vm/jit/jit.c, and parsed by src/vm/jit/verify/generate.pl!            */
+/*                                                                           */
+/* The comments at the start of the line and inside the braces are           */
+/* significant. If you want to add a comment to an ICMD, do that after the   */
+/* comma, or brace, at the end of the line.                                  */
+/*                                                                           */
+/* The format is as follows (slashes reversed for obvious reasons):          */
+/*                                                                           */
+/* \*#*\ { N( name )  data-flow, control-flow, flags \* stage (action) *\ }  */
+/*                                                                           */
+/*  ^^^                                                                      */
+/* opcode                                                                    */
+/*                                                                           */
+/* where                                                                     */
+/*     opcode...........is the opcode number (decimal)                       */
+/*     name.............is the quoted name without the ICMD_ prefix          */
+/*     data-flow........is one of the DF_ constants (see jit.h)              */
+/*     control-flow.....is one of the CF_ constants (see jit.h)              */
+/*     flags............is 0 or a |-combination of                           */
+/*                          PEI........may throw an exception                */
+/*                          CALLS......needs saved registers (calls out)     */
+/*                          *_CALLS....see jit.h for architecture specific   */
+/*                                     constants to put here                 */
+/*                                                                           */
+/*     stage............is either empty, or one of                           */
+/*                          --         ICMD is not used anywhere after parse */
+/*                          -S         ICMD is eliminated by stack_analyse   */
+/*                          S+         ICMD is introduced by stack_analyse   */
+/*                                                                           */
+/*     action...........is the stack action of the ICMD in the notation      */
+/*                      instack--outstack, TOS being rightmost.              */
+/*                                                                           */
+/*                      Valid type characters are                            */
+/*                          I, L, F, D, and A      the basic types           */
+/*                          1                      a category 1 type         */
+/*                          2                      a category 2 type         */
+/*                          .                      variable number of slots  */
+/*                                                                           */
+/*                      Whitespace is not allowed within the action.         */
+/*                                                                           */
+/*                      Some ICMDs may have several variants. In this case   */
+/*                      the action is build by joining the individual        */
+/*                      actions of the variants with |.                      */
+/*                                                                           */
+/*                                                                           */
+/* CAUTION: Do not use preprocessor directives in this file! They will       */
+/*          confuse the generator.                                           */
+/*                                                                           */
+
+
+/*  0*/ {N("NOP            ") DF_0_TO_0 , CF_NORMAL, 0              /*    (--)                 */},
+/*  1*/ {N("ACONST         ") DF_0_TO_1 , CF_NORMAL, PEI            /*    (--A)                */},
+/*  2*/ {N("CHECKNULL      ") DF_1_TO_1 , CF_NORMAL, PEI            /*    (A--A)               */},
+/*  3*/ {N("ICONST         ") DF_0_TO_1 , CF_NORMAL, 0              /*    (--I)                */},
+/*  4*/ {N("UNDEF4         ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
+/*  5*/ {N("IDIVPOW2       ") DF_1_TO_1 , CF_NORMAL, 0              /* S+ (I--I)               */},
+/*  6*/ {N("LDIVPOW2       ") DF_1_TO_1 , CF_NORMAL, 0              /* S+ (L--L)               */},
+/*  7*/ {N("UNDEF7         ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
+/*  8*/ {N("UNDEF8         ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
+/*  9*/ {N("LCONST         ") DF_0_TO_1 , CF_NORMAL, 0              /*    (--L)                */},
+/* 10*/ {N("LCMPCONST      ") DF_1_TO_1 , CF_NORMAL, 0              /* S+ (L--I)               */},
+/* 11*/ {N("FCONST         ") DF_0_TO_1 , CF_NORMAL, 0              /*    (--F)                */},
+/* 12*/ {N("UNDEF12        ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
+/* 13*/ {N("UNDEF13        ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
+/* 14*/ {N("DCONST         ") DF_0_TO_1 , CF_NORMAL, 0              /*    (--D)                */},
+/* 15*/ {N("COPY           ") DF_COPY   , CF_NORMAL, 0              /* S+ (1--1)               */},
+/* 16*/ {N("MOVE           ") DF_MOVE   , CF_NORMAL, 0              /* S+ (1--1)               */},
+/* 17*/ {N("UNDEF17        ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
+/* 18*/ {N("UNDEF18        ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
+/* 19*/ {N("UNDEF19        ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
+/* 20*/ {N("UNDEF20        ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
+/* 21*/ {N("ILOAD          ") DF_LOAD   , CF_NORMAL, 0              /*    (--I)                */},
+/* 22*/ {N("LLOAD          ") DF_LOAD   , CF_NORMAL, 0              /*    (--L)                */},
+/* 23*/ {N("FLOAD          ") DF_LOAD   , CF_NORMAL, 0              /*    (--F)                */},
+/* 24*/ {N("DLOAD          ") DF_LOAD   , CF_NORMAL, 0              /*    (--D)                */},
+/* 25*/ {N("ALOAD          ") DF_LOAD   , CF_NORMAL, 0              /*    (--A)                */},
+/* 26*/ {N("IADDCONST      ") DF_1_TO_1 , CF_NORMAL, 0              /* S+ (I--I)               */},
+/* 27*/ {N("ISUBCONST      ") DF_1_TO_1 , CF_NORMAL, 0              /* S+ (I--I)               */},
+/* 28*/ {N("IMULCONST      ") DF_1_TO_1 , CF_NORMAL, 0              /* S+ (I--I)               */},
+/* 29*/ {N("IANDCONST      ") DF_1_TO_1 , CF_NORMAL, 0              /* S+ (I--I)               */},
+/* 30*/ {N("IORCONST       ") DF_1_TO_1 , CF_NORMAL, 0              /* S+ (I--I)               */},
+/* 31*/ {N("IXORCONST      ") DF_1_TO_1 , CF_NORMAL, 0              /* S+ (I--I)               */},
+/* 32*/ {N("ISHLCONST      ") DF_1_TO_1 , CF_NORMAL, 0              /* S+ (I--I)               */},
+/* 33*/ {N("ISHRCONST      ") DF_1_TO_1 , CF_NORMAL, 0              /* S+ (I--I)               */},
+/* 34*/ {N("IUSHRCONST     ") DF_1_TO_1 , CF_NORMAL, 0              /* S+ (I--I)               */},
+/* 35*/ {N("IREMPOW2       ") DF_1_TO_1 , CF_NORMAL, 0              /* S+ (I--I)               */},
+/* 36*/ {N("LADDCONST      ") DF_1_TO_1 , CF_NORMAL, 0              /* S+ (L--L)               */},
+/* 37*/ {N("LSUBCONST      ") DF_1_TO_1 , CF_NORMAL, 0              /* S+ (L--L)               */},
+/* 38*/ {N("LMULCONST      ") DF_1_TO_1 , CF_NORMAL, 0              /* S+ (L--L)               */},
+/* 39*/ {N("LANDCONST      ") DF_1_TO_1 , CF_NORMAL, 0              /* S+ (L--L)               */},
+/* 40*/ {N("LORCONST       ") DF_1_TO_1 , CF_NORMAL, 0              /* S+ (L--L)               */},
+/* 41*/ {N("LXORCONST      ") DF_1_TO_1 , CF_NORMAL, 0              /* S+ (L--L)               */},
+/* 42*/ {N("LSHLCONST      ") DF_1_TO_1 , CF_NORMAL, 0              /* S+ (L--L)               */},
+/* 43*/ {N("LSHRCONST      ") DF_1_TO_1 , CF_NORMAL, 0              /* S+ (L--L)               */},
+/* 44*/ {N("LUSHRCONST     ") DF_1_TO_1 , CF_NORMAL, 0              /* S+ (L--L)               */},
+/* 45*/ {N("LREMPOW2       ") DF_1_TO_1 , CF_NORMAL, 0              /* S+ (L--L)               */},
+/* 46*/ {N("IALOAD         ") DF_2_TO_1 , CF_NORMAL, PEI            /*    (AI--I)              */},
+/* 47*/ {N("LALOAD         ") DF_2_TO_1 , CF_NORMAL, PEI            /*    (AI--L)              */},
+/* 48*/ {N("FALOAD         ") DF_2_TO_1 , CF_NORMAL, PEI            /*    (AI--F)              */},
+/* 49*/ {N("DALOAD         ") DF_2_TO_1 , CF_NORMAL, PEI            /*    (AI--D)              */},
+/* 50*/ {N("AALOAD         ") DF_2_TO_1 , CF_NORMAL, PEI            /*    (AI--A)              */},
+/* 51*/ {N("BALOAD         ") DF_2_TO_1 , CF_NORMAL, PEI            /*    (AI--I)              */},
+/* 52*/ {N("CALOAD         ") DF_2_TO_1 , CF_NORMAL, PEI            /*    (AI--I)              */},
+/* 53*/ {N("SALOAD         ") DF_2_TO_1 , CF_NORMAL, PEI            /*    (AI--I)              */},
+/* 54*/ {N("ISTORE         ") DF_STORE  , CF_NORMAL, 0              /*    (I--)                */},
+/* 55*/ {N("LSTORE         ") DF_STORE  , CF_NORMAL, 0              /*    (L--)                */},
+/* 56*/ {N("FSTORE         ") DF_STORE  , CF_NORMAL, 0              /*    (F--)                */},
+/* 57*/ {N("DSTORE         ") DF_STORE  , CF_NORMAL, 0              /*    (D--)                */},
+/* 58*/ {N("ASTORE         ") DF_STORE  , CF_NORMAL, 0              /*    (A--|R--)            */},
+/* 59*/ {N("IF_LEQ         ") DF_1_TO_0 , CF_IF    , 0              /* S+ (L--)                */},
+/* 60*/ {N("IF_LNE         ") DF_1_TO_0 , CF_IF    , 0              /* S+ (L--)                */},
+/* 61*/ {N("IF_LLT         ") DF_1_TO_0 , CF_IF    , 0              /* S+ (L--)                */},
+/* 62*/ {N("IF_LGE         ") DF_1_TO_0 , CF_IF    , 0              /* S+ (L--)                */},
+/* 63*/ {N("IF_LGT         ") DF_1_TO_0 , CF_IF    , 0              /* S+ (L--)                */},
+/* 64*/ {N("IF_LLE         ") DF_1_TO_0 , CF_IF    , 0              /* S+ (L--)                */},
+/* 65*/ {N("IF_LCMPEQ      ") DF_2_TO_0 , CF_IF    , 0              /* S+ (LL--)               */},
+/* 66*/ {N("IF_LCMPNE      ") DF_2_TO_0 , CF_IF    , 0              /* S+ (LL--)               */},
+/* 67*/ {N("IF_LCMPLT      ") DF_2_TO_0 , CF_IF    , 0              /* S+ (LL--)               */},
+/* 68*/ {N("IF_LCMPGE      ") DF_2_TO_0 , CF_IF    , 0              /* S+ (LL--)               */},
+/* 69*/ {N("IF_LCMPGT      ") DF_2_TO_0 , CF_IF    , 0              /* S+ (LL--)               */},
+/* 70*/ {N("IF_LCMPLE      ") DF_2_TO_0 , CF_IF    , 0              /* S+ (LL--)               */},
+/* 71*/ {N("UNDEF71        ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
+/* 72*/ {N("UNDEF72        ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
+/* 73*/ {N("UNDEF73        ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
+/* 74*/ {N("UNDEF74        ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
+/* 75*/ {N("UNDEF75        ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
+/* 76*/ {N("UNDEF76        ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
+/* 77*/ {N("UNDEF77        ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
+/* 78*/ {N("UNDEF78        ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
+/* 79*/ {N("IASTORE        ") DF_3_TO_0 , CF_NORMAL, PEI            /*    (AII--)              */},
+/* 80*/ {N("LASTORE        ") DF_3_TO_0 , CF_NORMAL, PEI            /*    (AIL--)              */},
+/* 81*/ {N("FASTORE        ") DF_3_TO_0 , CF_NORMAL, PEI            /*    (AIF--)              */},
+/* 82*/ {N("DASTORE        ") DF_3_TO_0 , CF_NORMAL, PEI            /*    (AID--)              */},
+/* 83*/ {N("AASTORE        ") DF_3_TO_0 , CF_NORMAL, PEI|CALLS      /*    (AIA--)              */},
+/* 84*/ {N("BASTORE        ") DF_3_TO_0 , CF_NORMAL, PEI            /*    (AII--)              */},
+/* 85*/ {N("CASTORE        ") DF_3_TO_0 , CF_NORMAL, PEI            /*    (AII--)              */},
+/* 86*/ {N("SASTORE        ") DF_3_TO_0 , CF_NORMAL, PEI            /*    (AII--)              */},
+/* 87*/ {N("POP            ") DF_POP    , CF_NORMAL, 0              /*    (1--)                */},
+/* 88*/ {N("POP2           ") DF_POP2   , CF_NORMAL, 0              /*    (11--|2--)           */},
+/* 89*/ {N("DUP            ") DF_DUP    , CF_NORMAL, 0              /* -S (1--11)              */},
+/* 90*/ {N("DUP_X1         ") DF_DUP_X1 , CF_NORMAL, 0              /* -S (11--111)            */},
+/* 91*/ {N("DUP_X2         ") DF_DUP_X2 , CF_NORMAL, 0              /* -S (111--1111|21--121)  */},
+/* 92*/ {N("DUP2           ") DF_DUP2   , CF_NORMAL, 0              /* -S (11--1111|2--22)     */},
+/* 93*/ {N("DUP2_X1        ") DF_DUP2_X1, CF_NORMAL, 0              /* -S (111--11111|12--212) */},
+/* 94*/ {N("DUP2_X2        ") DF_DUP2_X2, CF_NORMAL, 0              /* -S (1111--111111|112--2112|22--222|211--11211) */},
+/* 95*/ {N("SWAP           ") DF_SWAP   , CF_NORMAL, 0              /* -S (11--11)             */},
+/* 96*/ {N("IADD           ") DF_2_TO_1 , CF_NORMAL, 0              /*    (II--I)              */},
+/* 97*/ {N("LADD           ") DF_2_TO_1 , CF_NORMAL, 0              /*    (LL--L)              */},
+/* 98*/ {N("FADD           ") DF_2_TO_1 , CF_NORMAL, 0              /*    (FF--F)              */},
+/* 99*/ {N("DADD           ") DF_2_TO_1 , CF_NORMAL, 0              /*    (DD--D)              */},
+/*100*/ {N("ISUB           ") DF_2_TO_1 , CF_NORMAL, 0              /*    (II--I)              */},
+/*101*/ {N("LSUB           ") DF_2_TO_1 , CF_NORMAL, 0              /*    (LL--L)              */},
+/*102*/ {N("FSUB           ") DF_2_TO_1 , CF_NORMAL, 0              /*    (FF--F)              */},
+/*103*/ {N("DSUB           ") DF_2_TO_1 , CF_NORMAL, 0              /*    (DD--D)              */},
+/*104*/ {N("IMUL           ") DF_2_TO_1 , CF_NORMAL, 0              /*    (II--I)              */},
+/*105*/ {N("LMUL           ") DF_2_TO_1 , CF_NORMAL, 0              /*    (LL--L)              */},
+/*106*/ {N("FMUL           ") DF_2_TO_1 , CF_NORMAL, 0              /*    (FF--F)              */},
+/*107*/ {N("DMUL           ") DF_2_TO_1 , CF_NORMAL, 0              /*    (DD--D)              */},
+/*108*/ {N("IDIV           ") DF_2_TO_1 , CF_NORMAL, PEI|IDIV_CALLS /*    (II--I)              */},
+/*109*/ {N("LDIV           ") DF_2_TO_1 , CF_NORMAL, PEI|LDIV_CALLS /*    (LL--L)              */},
+/*110*/ {N("FDIV           ") DF_2_TO_1 , CF_NORMAL, 0              /*    (FF--F)              */},
+/*111*/ {N("DDIV           ") DF_2_TO_1 , CF_NORMAL, 0              /*    (DD--D)              */},
+/*112*/ {N("IREM           ") DF_2_TO_1 , CF_NORMAL, PEI|IDIV_CALLS /*    (II--I)              */},
+/*113*/ {N("LREM           ") DF_2_TO_1 , CF_NORMAL, PEI|LDIV_CALLS /*    (LL--L)              */},
+/*114*/ {N("FREM           ") DF_2_TO_1 , CF_NORMAL, 0              /*    (FF--F)              */},
+/*115*/ {N("DREM           ") DF_2_TO_1 , CF_NORMAL, 0              /*    (DD--D)              */},
+/*116*/ {N("INEG           ") DF_1_TO_1 , CF_NORMAL, 0              /*    (I--I)               */},
+/*117*/ {N("LNEG           ") DF_1_TO_1 , CF_NORMAL, 0              /*    (L--L)               */},
+/*118*/ {N("FNEG           ") DF_1_TO_1 , CF_NORMAL, 0              /*    (F--F)               */},
+/*119*/ {N("DNEG           ") DF_1_TO_1 , CF_NORMAL, 0              /*    (D--D)               */},
+/*120*/ {N("ISHL           ") DF_2_TO_1 , CF_NORMAL, 0              /*    (II--I)              */},
+/*121*/ {N("LSHL           ") DF_2_TO_1 , CF_NORMAL, 0              /*    (LI--L)              */},
+/*122*/ {N("ISHR           ") DF_2_TO_1 , CF_NORMAL, 0              /*    (II--I)              */},
+/*123*/ {N("LSHR           ") DF_2_TO_1 , CF_NORMAL, 0              /*    (LI--L)              */},
+/*124*/ {N("IUSHR          ") DF_2_TO_1 , CF_NORMAL, 0              /*    (II--I)              */},
+/*125*/ {N("LUSHR          ") DF_2_TO_1 , CF_NORMAL, 0              /*    (LI--L)              */},
+/*126*/ {N("IAND           ") DF_2_TO_1 , CF_NORMAL, 0              /*    (II--I)              */},
+/*127*/ {N("LAND           ") DF_2_TO_1 , CF_NORMAL, 0              /*    (LL--L)              */},
+/*128*/ {N("IOR            ") DF_2_TO_1 , CF_NORMAL, 0              /*    (II--I)              */},
+/*129*/ {N("LOR            ") DF_2_TO_1 , CF_NORMAL, 0              /*    (LL--L)              */},
+/*130*/ {N("IXOR           ") DF_2_TO_1 , CF_NORMAL, 0              /*    (II--I)              */},
+/*131*/ {N("LXOR           ") DF_2_TO_1 , CF_NORMAL, 0              /*    (LL--L)              */},
+/*132*/ {N("IINC           ") DF_IINC   , CF_NORMAL, 0              /*    (--)                 */},
+/*133*/ {N("I2L            ") DF_1_TO_1 , CF_NORMAL, 0              /*    (I--L)               */},
+/*134*/ {N("I2F            ") DF_1_TO_1 , CF_NORMAL, 0              /*    (I--F)               */},
+/*135*/ {N("I2D            ") DF_1_TO_1 , CF_NORMAL, 0              /*    (I--D)               */},
+/*136*/ {N("L2I            ") DF_1_TO_1 , CF_NORMAL, 0              /*    (L--I)               */},
+/*137*/ {N("L2F            ") DF_1_TO_1 , CF_NORMAL, 0              /*    (L--F)               */},
+/*138*/ {N("L2D            ") DF_1_TO_1 , CF_NORMAL, 0              /*    (L--D)               */},
+/*139*/ {N("F2I            ") DF_1_TO_1 , CF_NORMAL, 0              /*    (F--I)               */},
+/*140*/ {N("F2L            ") DF_1_TO_1 , CF_NORMAL, 0              /*    (F--L)               */},
+/*141*/ {N("F2D            ") DF_1_TO_1 , CF_NORMAL, 0              /*    (F--D)               */},
+/*142*/ {N("D2I            ") DF_1_TO_1 , CF_NORMAL, 0              /*    (D--I)               */},
+/*143*/ {N("D2L            ") DF_1_TO_1 , CF_NORMAL, 0              /*    (D--L)               */},
+/*144*/ {N("D2F            ") DF_1_TO_1 , CF_NORMAL, 0              /*    (D--F)               */},
+/*145*/ {N("INT2BYTE       ") DF_1_TO_1 , CF_NORMAL, 0              /*    (I--I)               */},
+/*146*/ {N("INT2CHAR       ") DF_1_TO_1 , CF_NORMAL, 0              /*    (I--I)               */},
+/*147*/ {N("INT2SHORT      ") DF_1_TO_1 , CF_NORMAL, 0              /*    (I--I)               */},
+/*148*/ {N("LCMP           ") DF_2_TO_1 , CF_NORMAL, 0              /*    (LL--I)              */},
+/*149*/ {N("FCMPL          ") DF_2_TO_1 , CF_NORMAL, 0              /*    (FF--I)              */},
+/*150*/ {N("FCMPG          ") DF_2_TO_1 , CF_NORMAL, 0              /*    (FF--I)              */},
+/*151*/ {N("DCMPL          ") DF_2_TO_1 , CF_NORMAL, 0              /*    (DD--I)              */},
+/*152*/ {N("DCMPG          ") DF_2_TO_1 , CF_NORMAL, 0              /*    (DD--I)              */},
+/*153*/ {N("IFEQ           ") DF_1_TO_0 , CF_IF    , 0              /*    (I--)                */},
+/*154*/ {N("IFNE           ") DF_1_TO_0 , CF_IF    , 0              /*    (I--)                */},
+/*155*/ {N("IFLT           ") DF_1_TO_0 , CF_IF    , 0              /*    (I--)                */},
+/*156*/ {N("IFGE           ") DF_1_TO_0 , CF_IF    , 0              /*    (I--)                */},
+/*157*/ {N("IFGT           ") DF_1_TO_0 , CF_IF    , 0              /*    (I--)                */},
+/*158*/ {N("IFLE           ") DF_1_TO_0 , CF_IF    , 0              /*    (I--)                */},
+/*159*/ {N("IF_ICMPEQ      ") DF_2_TO_0 , CF_IF    , 0              /*    (II--)               */},
+/*160*/ {N("IF_ICMPNE      ") DF_2_TO_0 , CF_IF    , 0              /*    (II--)               */},
+/*161*/ {N("IF_ICMPLT      ") DF_2_TO_0 , CF_IF    , 0              /*    (II--)               */},
+/*162*/ {N("IF_ICMPGE      ") DF_2_TO_0 , CF_IF    , 0              /*    (II--)               */},
+/*163*/ {N("IF_ICMPGT      ") DF_2_TO_0 , CF_IF    , 0              /*    (II--)               */},
+/*164*/ {N("IF_ICMPLE      ") DF_2_TO_0 , CF_IF    , 0              /*    (II--)               */},
+/*165*/ {N("IF_ACMPEQ      ") DF_2_TO_0 , CF_IF    , 0              /*    (AA--)               */},
+/*166*/ {N("IF_ACMPNE      ") DF_2_TO_0 , CF_IF    , 0              /*    (AA--)               */},
+/*167*/ {N("GOTO           ") DF_0_TO_0 , CF_GOTO  , 0              /*    (--)                 */},
+/*168*/ {N("JSR            ") DF_0_TO_1 , CF_JSR   , 0              /*    (--R)                */},
+/*169*/ {N("RET            ") DF_0_TO_0 , CF_RET   , 0              /*    (--)                 */},
+/*170*/ {N("TABLESWITCH    ") DF_1_TO_0 , CF_TABLE , 0              /*    (I--)                */},
+/*171*/ {N("LOOKUPSWITCH   ") DF_1_TO_0 , CF_LOOKUP, 0              /*    (I--)                */},
+/*172*/ {N("IRETURN        ") DF_1_TO_0 , CF_END   , 0              /*    (I--)                */},
+/*173*/ {N("LRETURN        ") DF_1_TO_0 , CF_END   , 0              /*    (L--)                */},
+/*174*/ {N("FRETURN        ") DF_1_TO_0 , CF_END   , 0              /*    (F--)                */},
+/*175*/ {N("DRETURN        ") DF_1_TO_0 , CF_END   , 0              /*    (D--)                */},
+/*176*/ {N("ARETURN        ") DF_1_TO_0 , CF_END   , PEI            /*    (A--)                */},
+/*177*/ {N("RETURN         ") DF_0_TO_0 , CF_END   , 0              /*    (--)                 */},
+/*178*/ {N("GETSTATIC      ") DF_0_TO_1 , CF_NORMAL, PEI            /*    (--1|--2)            */},
+/*179*/ {N("PUTSTATIC      ") DF_1_TO_0 , CF_NORMAL, PEI            /*    (1--|2--)            */},
+/*180*/ {N("GETFIELD       ") DF_1_TO_1 , CF_NORMAL, PEI            /*    (A--1|A--2)          */},
+/*181*/ {N("PUTFIELD       ") DF_2_TO_0 , CF_NORMAL, PEI            /*    (A1--|A2--)          */},
+/*182*/ {N("INVOKEVIRTUAL  ") DF_INVOKE , CF_NORMAL, PEI|CALLS      /*    (.--1|.--2|.--)      */},
+/*183*/ {N("INVOKESPECIAL  ") DF_INVOKE , CF_NORMAL, PEI|CALLS      /*    (.--1|.--2|.--)      */},
+/*184*/ {N("INVOKESTATIC   ") DF_INVOKE , CF_NORMAL, PEI|CALLS      /*    (.--1|.--2|.--)      */},
+/*185*/ {N("INVOKEINTERFACE") DF_INVOKE , CF_NORMAL, PEI|CALLS      /*    (.--1|.--2|.--)      */},
+/*186*/ {N("UNDEF186       ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
+/*187*/ {N("NEW            ") DF_0_TO_1 , CF_NORMAL, PEI            /* -- (--A)                */},
+/*188*/ {N("NEWARRAY       ") DF_0_TO_1 , CF_NORMAL, PEI            /* -- (--A)                */},
+/*189*/ {N("ANEWARRAY      ") DF_0_TO_1 , CF_NORMAL, PEI            /* -- (--A)                */},
+/*190*/ {N("ARRAYLENGTH    ") DF_1_TO_1 , CF_NORMAL, PEI            /*    (A--I)               */},
+/*191*/ {N("ATHROW         ") DF_1_TO_0 , CF_END   , PEI            /*    (A--)                */},
+/*192*/ {N("CHECKCAST      ") DF_1_TO_1 , CF_NORMAL, PEI|CALLS      /*    (A--A)               */},
+/*193*/ {N("INSTANCEOF     ") DF_1_TO_1 , CF_NORMAL, PEI|CALLS      /*    (A--I)               */},
+/*194*/ {N("MONITORENTER   ") DF_1_TO_0 , CF_NORMAL, PEI|CALLS      /* -- (A--)                */},
+/*195*/ {N("MONITOREXIT    ") DF_1_TO_0 , CF_NORMAL, PEI|CALLS      /* -- (A--)                */},
+/*196*/ {N("UNDEF196       ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
+/*197*/ {N("MULTIANEWARRAY ") DF_N_TO_1 , CF_NORMAL, PEI|CALLS      /*    (.--A)               */},
+/*198*/ {N("IFNULL         ") DF_1_TO_0 , CF_IF    , 0              /*    (A--)                */},
+/*199*/ {N("IFNONNULL      ") DF_1_TO_0 , CF_IF    , 0              /*    (A--)                */},
+/*200*/ {N("UNDEF200       ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
+/*201*/ {N("UNDEF201       ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
+/*202*/ {N("UNDEF202       ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
+/*203*/ {N("UNDEF203       ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
+/*204*/ {N("IASTORECONST   ") DF_2_TO_0 , CF_NORMAL, PEI            /* S+ (AI--)               */},
+/*205*/ {N("LASTORECONST   ") DF_2_TO_0 , CF_NORMAL, PEI            /* S+ (AI--)               */},
+/*206*/ {N("FASTORECONST   ") DF_2_TO_0 , CF_NORMAL, PEI            /* S+ (AI--)               */},
+/*207*/ {N("DASTORECONST   ") DF_2_TO_0 , CF_NORMAL, PEI            /* S+ (AI--)               */},
+/*208*/ {N("AASTORECONST   ") DF_2_TO_0 , CF_NORMAL, PEI            /* S+ (AI--)               */},
+/*209*/ {N("BASTORECONST   ") DF_2_TO_0 , CF_NORMAL, PEI            /* S+ (AI--)               */},
+/*210*/ {N("CASTORECONST   ") DF_2_TO_0 , CF_NORMAL, PEI            /* S+ (AI--)               */},
+/*211*/ {N("SASTORECONST   ") DF_2_TO_0 , CF_NORMAL, PEI            /* S+ (AI--)               */},
+/*212*/ {N("PUTSTATICCONST ") DF_0_TO_0 , CF_NORMAL, PEI            /* S+ (--)                 */},
+/*213*/ {N("PUTFIELDCONST  ") DF_1_TO_0 , CF_NORMAL, PEI            /* S+ (A--)                */},
+/*214*/ {N("IMULPOW2       ") DF_1_TO_1 , CF_NORMAL, 0              /* S+ (I--I)               */},
+/*215*/ {N("LMULPOW2       ") DF_1_TO_1 , CF_NORMAL, 0              /* S+ (L--L)               */},
+/*216*/ {N("IF_FCMPEQ      ") DF_0_TO_0 , CF_IF    , 0              /* -- ()                   */},
+/*217*/ {N("IF_FCMPNE      ") DF_0_TO_0 , CF_IF    , 0              /* -- ()                   */},
+/*218*/ {N("IF_FCMPL_LT    ") DF_0_TO_0 , CF_IF    , 0              /* -- ()                   */},
+/*219*/ {N("IF_FCMPL_GE    ") DF_0_TO_0 , CF_IF    , 0              /* -- ()                   */},
+/*220*/ {N("IF_FCMPL_GT    ") DF_0_TO_0 , CF_IF    , 0              /* -- ()                   */},
+/*221*/ {N("IF_FCMPL_LE    ") DF_0_TO_0 , CF_IF    , 0              /* -- ()                   */},
+/*222*/ {N("IF_FCMPG_LT    ") DF_0_TO_0 , CF_IF    , 0              /* -- ()                   */},
+/*223*/ {N("IF_FCMPG_GE    ") DF_0_TO_0 , CF_IF    , 0              /* -- ()                   */},
+/*224*/ {N("IF_FCMPG_GT    ") DF_0_TO_0 , CF_IF    , 0              /* -- ()                   */},
+/*225*/ {N("IF_FCMPG_LE    ") DF_0_TO_0 , CF_IF    , 0              /* -- ()                   */},
+/*226*/ {N("IF_DCMPEQ      ") DF_0_TO_0 , CF_IF    , 0              /* -- ()                   */},
+/*227*/ {N("IF_DCMPNE      ") DF_0_TO_0 , CF_IF    , 0              /* -- ()                   */},
+/*228*/ {N("IF_DCMPL_LT    ") DF_0_TO_0 , CF_IF    , 0              /* -- ()                   */},
+/*229*/ {N("IF_DCMPL_GE    ") DF_0_TO_0 , CF_IF    , 0              /* -- ()                   */},
+/*230*/ {N("IF_DCMPL_GT    ") DF_0_TO_0 , CF_IF    , 0              /* -- ()                   */},
+/*231*/ {N("IF_DCMPL_LE    ") DF_0_TO_0 , CF_IF    , 0              /* -- ()                   */},
+/*232*/ {N("IF_DCMPG_LT    ") DF_0_TO_0 , CF_IF    , 0              /* -- ()                   */},
+/*233*/ {N("IF_DCMPG_GE    ") DF_0_TO_0 , CF_IF    , 0              /* -- ()                   */},
+/*234*/ {N("IF_DCMPG_GT    ") DF_0_TO_0 , CF_IF    , 0              /* -- ()                   */},
+/*235*/ {N("IF_DCMPG_LE    ") DF_0_TO_0 , CF_IF    , 0              /* -- ()                   */},
+/*236*/ {N("UNDEF236       ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
+/*237*/ {N("UNDEF237       ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
+/*238*/ {N("UNDEF238       ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
+/*239*/ {N("UNDEF239       ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
+/*240*/ {N("UNDEF240       ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
+/*241*/ {N("UNDEF241       ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
+/*242*/ {N("UNDEF242       ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
+/*243*/ {N("UNDEF243       ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
+/*244*/ {N("UNDEF244       ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
+/*245*/ {N("UNDEF245       ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
+/*246*/ {N("UNDEF246       ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
+/*247*/ {N("UNDEF247       ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
+/*248*/ {N("UNDEF248       ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
+/*249*/ {N("GETEXCEPTION   ") DF_0_TO_1 , CF_NORMAL, 0              /* -- ()                   */},
+/*250*/ {N("PHI            ") DF_N_TO_1 , CF_NORMAL, 0              /* -- ()                   */},
+/*251*/ {N("INLINE_START   ") DF_0_TO_0 , CF_NORMAL, 0              /* S+ (--)                 */},
+/*252*/ {N("INLINE_END     ") DF_0_TO_0 , CF_NORMAL, 0              /* S+ (--)                 */},
+/*253*/ {N("INLINE_BODY    ") DF_0_TO_0 , CF_NORMAL, 0              /* S+ (--)                 */},
+/*254*/ {N("UNDEF254       ") DF_0_TO_0 , CF_NORMAL, 0              /* -- ()                   */},
+/*255*/ {N("BUILTIN        ") DF_BUILTIN, CF_NORMAL, PEI|CALLS      /*    (.--1|.--2|.--)      */}
+
diff --git a/src/vm/jit/ir/instruction.cpp b/src/vm/jit/ir/instruction.cpp
new file mode 100644 (file)
index 0000000..9be1a6f
--- /dev/null
@@ -0,0 +1,66 @@
+/* src/vm/jit/ir/instruction.cpp - IR instruction
+
+   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/descriptor.h"
+
+#include "vm/jit/ir/instruction.hpp"
+
+
+// REMOVEME
+extern "C" {
+
+methoddesc* instruction_call_site(const instruction* iptr)
+{
+       if (iptr->opc == ICMD_BUILTIN) {
+               return iptr->sx.s23.s3.bte->md;
+       }
+       else if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+               return iptr->sx.s23.s3.um->methodref->parseddesc.md;
+       }
+       else {
+               return iptr->sx.s23.s3.fmiref->p.method->parseddesc;
+       }
+}
+
+}
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
diff --git a/src/vm/jit/ir/instruction.hpp b/src/vm/jit/ir/instruction.hpp
new file mode 100644 (file)
index 0000000..c9f3e30
--- /dev/null
@@ -0,0 +1,277 @@
+/* src/vm/jit/ir/instruction.hpp - IR instruction
+
+   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 _INSTRUCTION_HPP
+#define _INSTRUCTION_HPP
+
+// Forward typedefs.
+typedef struct instruction instruction;
+typedef struct insinfo_inline insinfo_inline;
+
+
+#include "config.h"
+
+#include <stdint.h>
+
+#include "vm/descriptor.h"
+
+#include "vm/jit/jit.hpp"
+#include "vm/jit/replace.hpp"
+
+#include "vm/jit/ir/icmd.hpp"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Instruction structure.
+
+/* branch_target_t: used in TABLESWITCH tables */
+
+typedef union {
+    int32_t                    insindex; /* used in parse                     */
+    basicblock                *block;    /* valid after parse                 */
+} branch_target_t;
+
+/* lookup_target_t: used in LOOKUPSWITCH tables */
+
+typedef struct {
+    int32_t                    value;    /* case value                        */
+    branch_target_t            target;   /* branch target, see above          */
+} lookup_target_t;
+
+/*** s1 operand ***/
+
+typedef union {
+       int32_t                    varindex;
+       int32_t                    argcount;
+} s1_operand_t;
+
+/*** s2 operand ***/
+
+typedef union {
+       int32_t                    varindex;
+       int32_t                   *args;
+    classref_or_classinfo      c;
+    unresolved_class          *uc;
+    uintptr_t                  constval;         /* for PUT*CONST             */
+    int32_t                    tablelow;         /* for TABLESWITCH           */
+    uint32_t                   lookupcount;      /* for LOOKUPSWITCH          */
+       int32_t                    retaddrnr;        /* for ASTORE                */
+       instruction              **iargs;            /* for PHI                   */
+} s2_operand_t;
+
+/*** s3 operand ***/
+
+typedef union {
+       int32_t                    varindex;
+    uintptr_t                  constval;
+    classref_or_classinfo      c;
+    constant_FMIref           *fmiref;
+    unresolved_method         *um;
+    unresolved_field          *uf;
+    insinfo_inline            *inlineinfo;       /* for INLINE_START/END      */
+    int32_t                    tablehigh;        /* for TABLESWITCH           */
+    branch_target_t            lookupdefault;    /* for LOOKUPSWITCH          */
+    branch_target_t            jsrtarget;        /* for JSR                   */
+       int32_t                    javaindex;        /* for *STORE                */
+    struct builtintable_entry *bte;
+} s3_operand_t;
+
+/*** val operand ***/
+
+typedef union {
+    int32_t                   i;
+    int64_t                   l;
+    float                     f;
+    double                    d;
+    void                     *anyptr;
+    java_handle_t            *stringconst;       /* for ACONST with string    */
+    classref_or_classinfo     c;                 /* for ACONST with class     */
+} val_operand_t;
+
+/*** dst operand ***/
+
+typedef union {
+       int32_t                    varindex;
+    basicblock                *block;       /* valid after parse              */
+    branch_target_t           *table;       /* for TABLESWITCH                */
+    lookup_target_t           *lookup;      /* for LOOKUPSWITCH               */
+    int32_t                    insindex;    /* used in parse                  */
+} dst_operand_t;
+
+/*** flags (32 bits) ***/
+
+#define INS_FLAG_BASICBLOCK    0x01    /* marks a basic block start           */
+#define INS_FLAG_UNRESOLVED    0x02    /* contains unresolved field/meth/class*/
+#define INS_FLAG_CLASS         0x04    /* for ACONST, PUT*CONST with class    */
+#define INS_FLAG_ARRAY         0x08    /* for CHECKCAST/INSTANCEOF with array */
+#define INS_FLAG_CHECK         0x10    /* for *ALOAD|*ASTORE: check index     */
+                                       /* for BUILTIN: check exception        */
+#define INS_FLAG_KILL_PREV     0x04    /* for *STORE, invalidate prev local   */
+#define INS_FLAG_KILL_NEXT     0x08    /* for *STORE, invalidate next local   */
+#define INS_FLAG_RETADDR       0x10    /* for ASTORE: op is a returnAddress   */
+
+#define INS_FLAG_ID_SHIFT      5
+#define INS_FLAG_ID_MASK       (~0 << INS_FLAG_ID_SHIFT)
+
+typedef union {
+    u4                  bits;
+} flags_operand_t;
+
+
+// Instruction.
+
+/* The instruction format for the intermediate representation: */
+
+struct instruction {
+    u2                      opc;    /* opcode       */
+    u2                      line;   /* line number  */
+#if SIZEOF_VOID_P == 8
+    flags_operand_t         flags;  /* 4 bytes      */
+#endif
+    s1_operand_t            s1;     /* pointer-size */
+    union {
+        struct {
+            s2_operand_t    s2;     /* pointer-size */
+            s3_operand_t    s3;     /* pointer-size */
+        } s23;                      /*     XOR      */
+        val_operand_t       val;    /*  long-size   */
+    } sx;
+    dst_operand_t           dst;    /* pointer-size */
+#if SIZEOF_VOID_P == 4
+    flags_operand_t         flags;  /* 4 bytes      */
+#endif
+#if defined(ENABLE_ESCAPE_REASON)
+       void *escape_reasons;
+#endif
+};
+
+
+#define INSTRUCTION_STARTS_BASICBLOCK(iptr) \
+       ((iptr)->flags.bits & INS_FLAG_BASICBLOCK)
+
+#define INSTRUCTION_IS_RESOLVED(iptr) \
+       (!((iptr)->flags.bits & INS_FLAG_UNRESOLVED))
+
+#define INSTRUCTION_IS_UNRESOLVED(iptr) \
+       ((iptr)->flags.bits & INS_FLAG_UNRESOLVED)
+
+#define INSTRUCTION_MUST_CHECK(iptr) \
+       ((iptr)->flags.bits & INS_FLAG_CHECK)
+
+#define INSTRUCTION_GET_FIELDREF(iptr,fref) \
+       do { \
+               if (iptr->flags.bits & INS_FLAG_UNRESOLVED) \
+                       fref = iptr->sx.s23.s3.uf->fieldref; \
+               else \
+                       fref = iptr->sx.s23.s3.fmiref; \
+       } while (0)
+
+#define INSTRUCTION_GET_METHODREF(iptr,mref) \
+       do { \
+               if (iptr->flags.bits & INS_FLAG_UNRESOLVED) \
+                       mref = iptr->sx.s23.s3.um->methodref; \
+               else \
+                       mref = iptr->sx.s23.s3.fmiref; \
+       } while (0)
+
+#define INSTRUCTION_GET_METHODDESC(iptr, md) \
+       do { \
+               if (iptr->flags.bits & INS_FLAG_UNRESOLVED) \
+                       md = iptr->sx.s23.s3.um->methodref->parseddesc.md; \
+               else \
+                       md = iptr->sx.s23.s3.fmiref->parseddesc.md; \
+       } while (0)
+
+
+/* additional info structs for special instructions ***************************/
+
+/* for ICMD_INLINE_START and ICMD_INLINE_END */
+
+struct insinfo_inline {
+       /* fields copied from the inlining tree ----------------------------------*/
+       insinfo_inline *parent;     /* insinfo of the surrounding inlining, if any*/
+       methodinfo     *method;     /* the inlined method starting/ending here    */
+       methodinfo     *outer;      /* the outer method suspended/resumed here    */
+       int32_t         synclocal;      /* local index used for synchronization   */
+       bool            synchronize;    /* true if synchronization is needed      */
+       int32_t         throughcount;   /* total # of pass-through variables      */
+       int32_t         paramcount;     /* number of parameters of original call  */
+       int32_t         stackvarscount; /* source stackdepth at INLINE_START      */
+       int32_t        *stackvars;      /* stack vars at INLINE_START             */
+
+       /* fields set by inlining ------------------------------------------------*/
+       int32_t    *javalocals_start; /* javalocals at start of inlined body      */
+       int32_t    *javalocals_end;   /* javalocals after inlined body            */
+
+       /* fields set by replacement point creation ------------------------------*/
+#if defined(ENABLE_REPLACEMENT)
+       rplpoint   *rp;             /* replacement point at INLINE_START          */
+#endif
+
+       /* fields set by the codegen ---------------------------------------------*/
+       int32_t     startmpc;       /* machine code offset of start of inlining   */
+};
+
+
+/* Additional instruction accessors */
+
+methoddesc* instruction_call_site(const instruction* iptr);
+
+static inline bool instruction_has_dst(const instruction* iptr)
+{
+       if (
+               (icmd_table[iptr->opc].dataflow == DF_INVOKE) ||
+               (icmd_table[iptr->opc].dataflow == DF_BUILTIN)
+               ) {
+               return instruction_call_site(iptr)->returntype.type != TYPE_VOID;
+       }
+       else {
+               return icmd_table[iptr->opc].dataflow >= DF_DST_BASE;
+       }
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _INSTRUCTION_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:
+ */
diff --git a/src/vm/jit/jit.c b/src/vm/jit/jit.c
deleted file mode 100644 (file)
index 8f2dcf9..0000000
+++ /dev/null
@@ -1,1258 +0,0 @@
-/* src/vm/jit/jit.c - calls the code generation 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 "md.h"
-
-#include "mm/memory.h"
-
-#include "native/native.h"
-
-#include "toolbox/logging.h"
-
-#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/cfg.h"
-
-#include "vm/jit/codegen-common.h"
-#include "vm/jit/disass.h"
-#include "vm/jit/dseg.h"
-#include "vm/jit/jit.h"
-#include "vm/jit/parse.h"
-#include "vm/jit/reg.h"
-
-#include "vm/jit/show.h"
-#include "vm/jit/stack.h"
-
-#if defined(ENABLE_JITCACHE)
-# include "vm/jit/jitcache.hpp"
-#endif
-
-#if defined(ENABLE_OPAGENT)
-#include "vm/jit/oprofile-agent.hpp"
-#endif
-
-#include "vm/jit/allocator/simplereg.h"
-#if defined(ENABLE_LSRA) && !defined(ENABLE_SSA)
-# include "vm/jit/allocator/lsra.h"
-#endif
-
-#if defined(ENABLE_SSA)
-# include "vm/jit/optimizing/lsra.h"
-# include "vm/jit/optimizing/ssa.h"
-#endif
-
-#if defined(ENABLE_INLINING)
-# include "vm/jit/inline/inline.h"
-#endif
-
-#include "vm/jit/ir/bytecode.h"
-
-#include "vm/jit/loop/analyze.h"
-#include "vm/jit/loop/graph.h"
-#include "vm/jit/loop/loop.h"
-
-#if defined(ENABLE_IFCONV)
-# include "vm/jit/optimizing/ifconv.h"
-#endif
-
-#include "vm/jit/optimizing/reorder.h"
-
-#if defined(ENABLE_PYTHON)
-# include "vm/jit/python.h"
-#endif
-
-#include "vm/jit/verify/typecheck.h"
-
-
-/* debug macros ***************************************************************/
-
-#if !defined(NDEBUG)
-#define DEBUG_JIT_COMPILEVERBOSE(x)                            \
-    do {                                                                               \
-        if (compileverbose) {                                  \
-            log_message_method(x, m);                  \
-        }                                                                              \
-    } while (0)
-#else
-#define DEBUG_JIT_COMPILEVERBOSE(x)    /* nothing */
-#endif
-
-#if !defined(NDEBUG)
-# define TRACECOMPILERCALLS()                                                          \
-       do {                                                                                                    \
-               if (opt_TraceCompilerCalls) {                                           \
-                       log_start();                                                                    \
-                       log_print("[JIT compiler started: method=");    \
-                       method_print(m);                                                                \
-                       log_print("]");                                                                 \
-                       log_finish();                                                                   \
-               }                                                                                                       \
-       } while (0)
-#else
-# define TRACECOMPILERCALLS()
-#endif
-
-
-/* the ICMD table ************************************************************/
-
-#if !defined(NDEBUG)
-#define N(name)  name,
-#else
-#define N(name)
-#endif
-
-/* abbreviations for flags */
-
-#define PEI     ICMDTABLE_PEI
-#define CALLS   ICMDTABLE_CALLS
-
-/* some machine dependent values */
-
-#if SUPPORT_DIVISION
-#define IDIV_CALLS  0
-#else
-#define IDIV_CALLS  ICMDTABLE_CALLS
-#endif
-
-#if (SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
-#define LDIV_CALLS  0
-#else
-#define LDIV_CALLS  ICMDTABLE_CALLS
-#endif
-
-/* include the actual table */
-
-icmdtable_entry_t icmd_table[256] = {
-#include <vm/jit/icmdtable.inc>
-};
-
-#undef N
-#undef PEI
-#undef CALLS
-
-/* XXX hack until the old "PEI" definition is removed */
-#define PEI 1
-
-
-/* jit_init ********************************************************************
-
-   Initializes the JIT subsystem.
-
-*******************************************************************************/
-
-void jit_init(void)
-{
-       TRACESUBSYSTEMINITIALIZATION("jit_init");
-
-#if defined(ENABLE_JIT)
-       /* initialize stack analysis subsystem */
-
-       (void) stack_init();
-#endif
-
-       /* initialize show subsystem */
-
-#if !defined(NDEBUG)
-       (void) show_init();
-#endif
-
-       /* initialize codegen subsystem */
-
-       codegen_init();
-
-       /* initialize code subsystem */
-
-       (void) code_init();
-
-       /* Machine dependent initialization. */
-
-#if defined(ENABLE_JIT)
-# if defined(ENABLE_INTRP)
-       if (opt_intrp)
-               intrp_md_init();
-       else
-# endif
-               md_init();
-#else
-       intrp_md_init();
-#endif
-
-#if defined(ENABLE_OPAGENT)
-       if (opt_EnableOpagent)
-               OprofileAgent_initialize();
-#endif
-}
-
-
-/* jit_close *******************************************************************
-
-   Close the JIT subsystem.
-
-*******************************************************************************/
-
-void jit_close(void)
-{
-#if defined(ENABLE_OPAGENT)
-       if (opt_EnableOpagent)
-               OprofileAgent_close();
-#endif
-}
-
-
-/* dummy function, used when there is no JavaVM code available                */
-
-static u1 *do_nothing_function(void)
-{
-       return NULL;
-}
-
-
-/* jit_jitdata_new *************************************************************
-
-   Allocates and initalizes a new jitdata structure.
-
-*******************************************************************************/
-
-jitdata *jit_jitdata_new(methodinfo *m)
-{
-       jitdata  *jd;
-       codeinfo *code;
-
-       /* allocate jitdata structure and fill it */
-
-       jd = DNEW(jitdata);
-
-       jd->m     = m;
-       jd->cd    = DNEW(codegendata);
-       jd->rd    = DNEW(registerdata);
-#if defined(ENABLE_LOOP)
-       jd->ld    = DNEW(loopdata);
-#endif
-
-       /* Allocate codeinfo memory from the heap as we need to keep them. */
-
-       code = code_codeinfo_new(m);
-
-       /* Set codeinfo flags. */
-
-#if defined(ENABLE_THREADS)
-       if (checksync && (m->flags & ACC_SYNCHRONIZED))
-               code_flag_synchronized(code);
-
-       if (checksync && (m->flags & ACC_SYNCHRONIZED))
-               code_unflag_leafmethod(code);
-       else
-#endif
-               code_flag_leafmethod(code);
-
-       /* initialize variables */
-
-       jd->code                 = code;
-       jd->flags                = 0;
-       jd->exceptiontable       = NULL;
-       jd->exceptiontablelength = 0;
-       jd->returncount          = 0;
-       jd->branchtoentry        = false;
-       jd->branchtoend          = false;
-       jd->returncount          = 0;
-       jd->returnblock          = NULL;
-       jd->maxlocals            = m->maxlocals;
-
-       return jd;
-}
-
-
-/* jit_compile *****************************************************************
-
-   Translates one method to machine code.
-
-*******************************************************************************/
-
-static u1 *jit_compile_intern(jitdata *jd);
-
-u1 *jit_compile(methodinfo *m)
-{
-       u1      *r;
-       jitdata *jd;
-       int32_t  dumpmarker;
-
-       STATISTICS(count_jit_calls++);
-
-       /* Initialize the static function's class. */
-
-       /* ATTENTION: This MUST be done before the method lock is aquired,
-          otherwise we could run into a deadlock with <clinit>'s that
-          call static methods of it's own class. */
-
-       if ((m->flags & ACC_STATIC) && !(m->clazz->state & CLASS_INITIALIZED)) {
-#if !defined(NDEBUG)
-               if (initverbose)
-                       log_message_class("Initialize class ", m->clazz);
-#endif
-
-               if (!initialize_class(m->clazz))
-                       return NULL;
-
-               /* check if the method has been compiled during initialization */
-
-               if ((m->code != NULL) && (m->code->entrypoint != NULL))
-                       return m->code->entrypoint;
-       }
-
-       /* enter a monitor on the method */
-
-       LOCK_MONITOR_ENTER(m);
-
-       /* if method has been already compiled return immediately */
-
-       if (m->code != NULL) {
-               LOCK_MONITOR_EXIT(m);
-
-               assert(m->code->entrypoint);
-               return m->code->entrypoint;
-       }
-
-       TRACECOMPILERCALLS();
-
-       STATISTICS(count_methods++);
-
-#if defined (ENABLE_JITCACHE)
-
-       if (jitcache_load (m))
-       {
-               LOCK_MONITOR_EXIT(m);
-
-               return m->code->entrypoint;
-       }
-
-#endif
-
-#if defined(ENABLE_STATISTICS)
-       /* measure time */
-
-       if (opt_getcompilingtime)
-               compilingtime_start();
-#endif
-
-       /* mark start of dump memory area */
-
-       DMARKER;
-
-       /* create jitdata structure */
-
-       jd = jit_jitdata_new(m);
-
-       /* set the flags for the current JIT run */
-
-       jd->flags = JITDATA_FLAG_PARSE;
-
-#if defined(ENABLE_VERIFIER)
-       if (opt_verify)
-               jd->flags |= JITDATA_FLAG_VERIFY;
-#endif
-
-#if defined(ENABLE_PROFILING)
-       if (opt_prof)
-               jd->flags |= JITDATA_FLAG_INSTRUMENT;
-#endif
-
-#if defined(ENABLE_IFCONV)
-       if (opt_ifconv)
-               jd->flags |= JITDATA_FLAG_IFCONV;
-#endif
-
-#if defined(ENABLE_INLINING) && defined(ENABLE_INLINING_DEBUG)
-       if (opt_Inline && opt_InlineAll)
-               jd->flags |= JITDATA_FLAG_INLINE;
-#endif
-
-       if (opt_showintermediate)
-               jd->flags |= JITDATA_FLAG_SHOWINTERMEDIATE;
-
-       if (opt_showdisassemble)
-               jd->flags |= JITDATA_FLAG_SHOWDISASSEMBLE;
-
-       if (opt_verbosecall)
-               jd->flags |= JITDATA_FLAG_VERBOSECALL;
-
-#if defined(ENABLE_REPLACEMENT) && defined(ENABLE_INLINING)
-       if (opt_Inline && (jd->m->hitcountdown > 0) && (jd->code->optlevel == 0)) {
-               jd->flags |= JITDATA_FLAG_COUNTDOWN;
-       }
-#endif
-
-#if defined(ENABLE_JIT)
-# if defined(ENABLE_INTRP)
-       if (!opt_intrp)
-# endif
-               /* initialize the register allocator */
-       {
-               reg_setup(jd);
-       }
-#endif
-
-       /* setup the codegendata memory */
-
-       codegen_setup(jd);
-
-       /* now call internal compile function */
-
-       r = jit_compile_intern(jd);
-
-       if (r == NULL) {
-               /* We had an exception! Finish stuff here if necessary. */
-
-               /* release codeinfo */
-
-               code_codeinfo_free(jd->code);
-
-#if defined(ENABLE_PROFILING)
-               /* Release memory for basic block profiling information. */
-
-               if (JITDATA_HAS_FLAG_INSTRUMENT(jd))
-                       if (jd->code->bbfrequency != NULL)
-                               MFREE(jd->code->bbfrequency, u4, jd->code->basicblockcount);
-#endif
-       }
-       else {
-               DEBUG_JIT_COMPILEVERBOSE("Running: ");
-       }
-
-#if defined (ENABLE_JITCACHE)
-       jitcache_store(m);
-#endif
-
-       /* release dump area */
-
-       DRELEASE;
-
-#if defined(ENABLE_STATISTICS)
-       /* measure time */
-
-       if (opt_getcompilingtime)
-               compilingtime_stop();
-#endif
-
-#if defined(ENABLE_OPAGENT)
-       if (opt_EnableOpagent)
-               OprofileAgent_newmethod(m);
-#endif
-
-       /* leave the monitor */
-
-       LOCK_MONITOR_EXIT(m);
-
-       /* return pointer to the methods entry point */
-
-       return r;
-}
-
-
-/* jit_recompile ***************************************************************
-
-   Recompiles a Java method.
-
-*******************************************************************************/
-
-u1 *jit_recompile(methodinfo *m)
-{
-       u1      *r;
-       jitdata *jd;
-       u1       optlevel;
-       int32_t  dumpmarker;
-
-       /* check for max. optimization level */
-
-       optlevel = (m->code) ? m->code->optlevel : 0;
-
-#if 0
-       if (optlevel == 1) {
-/*             log_message_method("not recompiling: ", m); */
-               return NULL;
-       }
-#endif
-
-       DEBUG_JIT_COMPILEVERBOSE("Recompiling start: ");
-
-       STATISTICS(count_jit_calls++);
-
-#if defined(ENABLE_STATISTICS)
-       /* measure time */
-
-       if (opt_getcompilingtime)
-               compilingtime_start();
-#endif
-
-       /* mark start of dump memory area */
-
-       DMARKER;
-
-       /* create jitdata structure */
-
-       jd = jit_jitdata_new(m);
-
-       /* set the current optimization level to the previous one plus 1 */
-
-       jd->code->optlevel = optlevel + 1;
-
-       /* get the optimization flags for the current JIT run */
-
-#if defined(ENABLE_VERIFIER)
-       jd->flags |= JITDATA_FLAG_VERIFY;
-#endif
-
-       /* jd->flags |= JITDATA_FLAG_REORDER; */
-       if (opt_showintermediate)
-               jd->flags |= JITDATA_FLAG_SHOWINTERMEDIATE;
-       if (opt_showdisassemble)
-               jd->flags |= JITDATA_FLAG_SHOWDISASSEMBLE;
-       if (opt_verbosecall)
-               jd->flags |= JITDATA_FLAG_VERBOSECALL;
-
-#if defined(ENABLE_INLINING)
-       if (opt_Inline)
-               jd->flags |= JITDATA_FLAG_INLINE;
-#endif
-
-#if defined(ENABLE_JIT)
-# if defined(ENABLE_INTRP)
-       if (!opt_intrp)
-# endif
-               /* initialize the register allocator */
-
-               reg_setup(jd);
-#endif
-
-       /* setup the codegendata memory */
-
-       codegen_setup(jd);
-
-       /* now call internal compile function */
-
-       r = jit_compile_intern(jd);
-
-       if (r == NULL) {
-               /* We had an exception! Finish stuff here if necessary. */
-
-               /* release codeinfo */
-
-               code_codeinfo_free(jd->code);
-       }
-
-       /* release dump area */
-
-       DRELEASE;
-
-#if defined(ENABLE_STATISTICS)
-       /* measure time */
-
-       if (opt_getcompilingtime)
-               compilingtime_stop();
-#endif
-
-#if defined(ENABLE_OPAGENT)
-       if (opt_EnableOpagent)
-               OprofileAgent_newmethod(m);
-#endif
-
-       DEBUG_JIT_COMPILEVERBOSE("Recompiling done: ");
-
-       /* return pointer to the methods entry point */
-
-       return r;
-}
-
-#if defined(ENABLE_PM_HACKS)
-#include "vm/jit/jit_pm_1.inc"
-#endif
-
-/* jit_compile_intern **********************************************************
-
-   Static internal function which does the actual compilation.
-
-*******************************************************************************/
-
-static u1 *jit_compile_intern(jitdata *jd)
-{
-       methodinfo  *m;
-       codegendata *cd;
-       codeinfo    *code;
-
-#if defined(ENABLE_RT_TIMING)
-       struct timespec time_start,time_checks,time_parse,time_stack,
-                                       time_typecheck,time_loop,time_ifconv,time_alloc,
-                                       time_codegen;
-#endif
-       
-       RT_TIMING_GET_TIME(time_start);
-
-       /* get required compiler data */
-
-#if defined(ENABLE_LSRA) || defined(ENABLE_SSA)
-       jd->ls = NULL;
-#endif
-       m    = jd->m;
-       code = jd->code;
-       cd   = jd->cd;
-       
-#if defined(ENABLE_DEBUG_FILTER)
-       show_filters_apply(jd->m);
-#endif
-
-       /* Handle native methods and create a native stub. */
-
-       if (m->flags & ACC_NATIVE) {
-               functionptr f;
-
-               f = native_method_resolve(m);
-
-               if (f == NULL)
-                       return NULL;
-
-               code = codegen_generate_stub_native(m, f);
-
-               /* Native methods are never recompiled. */
-               
-               assert(!m->code);
-
-               m->code = code;
-               
-               return code->entrypoint;
-       }
-
-       /* if there is no javacode, print error message and return empty method   */
-
-       if (m->jcode == NULL) {
-               DEBUG_JIT_COMPILEVERBOSE("No code given for: ");
-
-               code->entrypoint = (u1 *) (ptrint) do_nothing_function;
-               m->code = code;
-
-               return code->entrypoint;        /* return empty method                */
-       }
-
-#if defined(ENABLE_STATISTICS)
-       if (opt_stat) {
-               count_javacodesize += m->jcodelength + 18;
-               count_tryblocks    += jd->exceptiontablelength;
-               count_javaexcsize  += jd->exceptiontablelength * SIZEOF_VOID_P;
-       }
-#endif
-
-       RT_TIMING_GET_TIME(time_checks);
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-       /* Code for Sun's OpenJDK (see
-          hotspot/src/share/vm/classfile/verifier.cpp
-          (Verifier::is_eligible_for_verification)): Don't verify
-          dynamically-generated bytecodes. */
-
-# if defined(ENABLE_VERIFIER)
-       if (class_issubclass(m->clazz, class_sun_reflect_MagicAccessorImpl))
-               jd->flags &= ~JITDATA_FLAG_VERIFY;
-# endif
-#endif
-
-       /* call the compiler passes ***********************************************/
-
-       DEBUG_JIT_COMPILEVERBOSE("Parsing: ");
-
-       /* call parse pass */
-
-       if (!parse(jd)) {
-               DEBUG_JIT_COMPILEVERBOSE("Exception while parsing: ");
-
-               return NULL;
-       }
-       RT_TIMING_GET_TIME(time_parse);
-
-       DEBUG_JIT_COMPILEVERBOSE("Parsing done: ");
-       
-#if defined(ENABLE_JIT)
-# if defined(ENABLE_INTRP)
-       if (!opt_intrp) {
-# endif
-               DEBUG_JIT_COMPILEVERBOSE("Analysing: ");
-
-               /* call stack analysis pass */
-
-               if (!stack_analyse(jd)) {
-                       DEBUG_JIT_COMPILEVERBOSE("Exception while analysing: ");
-
-                       return NULL;
-               }
-               RT_TIMING_GET_TIME(time_stack);
-
-               DEBUG_JIT_COMPILEVERBOSE("Analysing done: ");
-
-#ifdef ENABLE_VERIFIER
-               if (JITDATA_HAS_FLAG_VERIFY(jd)) {
-                       DEBUG_JIT_COMPILEVERBOSE("Typechecking: ");
-
-                       /* call typecheck pass */
-                       if (!typecheck(jd)) {
-                               DEBUG_JIT_COMPILEVERBOSE("Exception while typechecking: ");
-
-                               return NULL;
-                       }
-
-                       DEBUG_JIT_COMPILEVERBOSE("Typechecking done: ");
-               }
-#endif
-               RT_TIMING_GET_TIME(time_typecheck);
-
-#if defined(ENABLE_LOOP)
-               if (opt_loops) {
-                       depthFirst(jd);
-                       analyseGraph(jd);
-                       optimize_loops(jd);
-                       jit_renumber_basicblocks(jd);
-               }
-#endif
-               RT_TIMING_GET_TIME(time_loop);
-
-#if defined(ENABLE_IFCONV)
-               if (JITDATA_HAS_FLAG_IFCONV(jd)) {
-                       if (!ifconv_static(jd))
-                               return NULL;
-                       jit_renumber_basicblocks(jd);
-               }
-#endif
-               RT_TIMING_GET_TIME(time_ifconv);
-
-               /* inlining */
-
-#if defined(ENABLE_INLINING) && (!defined(ENABLE_ESCAPE) || 1)
-               if (JITDATA_HAS_FLAG_INLINE(jd)) {
-                       if (!inline_inline(jd))
-                               return NULL;
-               }
-#endif
-
-#if defined(ENABLE_SSA)
-               if (opt_lsra) {
-                       fix_exception_handlers(jd);
-               }
-#endif
-
-               /* Build the CFG.  This has to be done after stack_analyse, as
-                  there happens the JSR elimination. */
-
-               if (!cfg_build(jd))
-                       return NULL;
-
-#if defined(ENABLE_PROFILING)
-               /* Basic block reordering.  I think this should be done after
-                  if-conversion, as we could lose the ability to do the
-                  if-conversion. */
-
-               if (JITDATA_HAS_FLAG_REORDER(jd)) {
-                       if (!reorder(jd))
-                               return NULL;
-                       jit_renumber_basicblocks(jd);
-               }
-#endif
-
-#if defined(ENABLE_PM_HACKS)
-#include "vm/jit/jit_pm_2.inc"
-#endif
-               DEBUG_JIT_COMPILEVERBOSE("Allocating registers: ");
-
-#if defined(ENABLE_LSRA) && !defined(ENABLE_SSA)
-               /* allocate registers */
-               if (opt_lsra) {
-                       if (!lsra(jd))
-                               return NULL;
-
-                       STATISTICS(count_methods_allocated_by_lsra++);
-
-               } else
-# endif /* defined(ENABLE_LSRA) && !defined(ENABLE_SSA) */
-#if defined(ENABLE_SSA)
-               /* allocate registers */
-               if (
-                       (opt_lsra &&
-                       jd->code->optlevel > 0) 
-                       /* strncmp(jd->m->name->text, "hottie", 6) == 0*/
-                       /*&& jd->exceptiontablelength == 0*/
-               ) {
-                       /*printf("=== %s ===\n", jd->m->name->text);*/
-                       jd->ls = DNEW(lsradata);
-                       jd->ls = NULL;
-                       ssa(jd);
-                       /*lsra(jd);*/ regalloc(jd);
-                       /*eliminate_subbasicblocks(jd);*/
-                       STATISTICS(count_methods_allocated_by_lsra++);
-
-               } else
-# endif /* defined(ENABLE_SSA) */
-               {
-                       STATISTICS(count_locals_conflicts += (jd->maxlocals - 1) * (jd->maxlocals));
-
-                       regalloc(jd);
-               }
-
-               STATISTICS(simplereg_make_statistics(jd));
-
-               DEBUG_JIT_COMPILEVERBOSE("Allocating registers done: ");
-# if defined(ENABLE_INTRP)
-       }
-# endif
-#endif /* defined(ENABLE_JIT) */
-       RT_TIMING_GET_TIME(time_alloc);
-
-#if defined(ENABLE_PROFILING)
-       /* Allocate memory for basic block profiling information. This
-          _must_ be done after loop optimization and register allocation,
-          since they can change the basic block count. */
-
-       if (JITDATA_HAS_FLAG_INSTRUMENT(jd))
-               code->bbfrequency = MNEW(u4, jd->basicblockcount);
-#endif
-
-       DEBUG_JIT_COMPILEVERBOSE("Generating code: ");
-
-       /* now generate the machine code */
-
-#if defined(ENABLE_JIT)
-# if defined(ENABLE_INTRP)
-       if (opt_intrp) {
-#if defined(ENABLE_VERIFIER)
-               if (opt_verify) {
-                       DEBUG_JIT_COMPILEVERBOSE("Typechecking (stackbased): ");
-
-                       if (!typecheck_stackbased(jd)) {
-                               DEBUG_JIT_COMPILEVERBOSE("Exception while typechecking (stackbased): ");
-                               return NULL;
-                       }
-               }
-#endif
-               if (!intrp_codegen(jd)) {
-                       DEBUG_JIT_COMPILEVERBOSE("Exception while generating code: ");
-
-                       return NULL;
-               }
-       } else
-# endif
-               {
-                       if (!codegen_generate(jd)) {
-                               DEBUG_JIT_COMPILEVERBOSE("Exception while generating code: ");
-
-                               return NULL;
-                       }
-               }
-#else
-       if (!intrp_codegen(jd)) {
-               DEBUG_JIT_COMPILEVERBOSE("Exception while generating code: ");
-
-               return NULL;
-       }
-#endif
-       RT_TIMING_GET_TIME(time_codegen);
-
-       DEBUG_JIT_COMPILEVERBOSE("Generating code done: ");
-
-#if !defined(NDEBUG) && defined(ENABLE_REPLACEMENT)
-       /* activate replacement points inside newly created code */
-
-       if (opt_TestReplacement)
-               replace_activate_replacement_points(code, false);
-#endif
-
-#if !defined(NDEBUG)
-#if defined(ENABLE_DEBUG_FILTER)
-       if (jd->m->filtermatches & SHOW_FILTER_FLAG_SHOW_METHOD)
-#endif
-       {
-               /* intermediate and assembly code listings */
-               
-               if (JITDATA_HAS_FLAG_SHOWINTERMEDIATE(jd)) {
-                       show_method(jd, SHOW_CODE);
-               }
-               else if (JITDATA_HAS_FLAG_SHOWDISASSEMBLE(jd)) {
-# if defined(ENABLE_DISASSEMBLER)
-                       DISASSEMBLE(code->entrypoint,
-                                               code->entrypoint + (code->mcodelength - cd->dseglen));
-# endif
-               }
-
-               if (opt_showddatasegment)
-                       dseg_display(jd);
-       }
-#endif
-
-       /* switch to the newly generated code */
-
-       assert(code);
-       assert(code->entrypoint);
-
-       /* add the current compile version to the methodinfo */
-
-       code->prev = m->code;
-       m->code = code;
-
-       RT_TIMING_TIME_DIFF(time_start,time_checks,RT_TIMING_JIT_CHECKS);
-       RT_TIMING_TIME_DIFF(time_checks,time_parse,RT_TIMING_JIT_PARSE);
-       RT_TIMING_TIME_DIFF(time_parse,time_stack,RT_TIMING_JIT_STACK);
-       RT_TIMING_TIME_DIFF(time_stack,time_typecheck,RT_TIMING_JIT_TYPECHECK);
-       RT_TIMING_TIME_DIFF(time_typecheck,time_loop,RT_TIMING_JIT_LOOP);
-       RT_TIMING_TIME_DIFF(time_loop,time_alloc,RT_TIMING_JIT_ALLOC);
-       RT_TIMING_TIME_DIFF(time_alloc,time_codegen,RT_TIMING_JIT_CODEGEN);
-       RT_TIMING_TIME_DIFF(time_start,time_codegen,RT_TIMING_JIT_TOTAL);
-
-       /* return pointer to the methods entry point */
-
-       return code->entrypoint;
-} 
-
-
-/* jit_invalidate_code *********************************************************
-
-   Mark the compiled code of the given method as invalid and take care that
-   it is replaced if necessary.
-
-   XXX Not fully implemented, yet.
-
-*******************************************************************************/
-
-void jit_invalidate_code(methodinfo *m)
-{
-       codeinfo *code;
-
-       code = m->code;
-
-       if (code == NULL || code_is_invalid(code))
-               return;
-
-       code_flag_invalid(code);
-
-       /* activate mappable replacement points */
-
-#if defined(ENABLE_REPLACEMENT)
-       replace_activate_replacement_points(code, true);
-#else
-       vm_abort("invalidating code only works with ENABLE_REPLACEMENT");
-#endif
-}
-
-
-/* jit_request_optimization ****************************************************
-
-   Request optimization of the given method. If the code of the method is
-   unoptimized, it will be invalidated, so the next jit_get_current_code(m)
-   triggers an optimized recompilation.
-   If the method is already optimized, this function does nothing.
-
-   IN:
-       m................the method
-
-*******************************************************************************/
-
-void jit_request_optimization(methodinfo *m)
-{
-       codeinfo *code;
-
-       code = m->code;
-
-       if (code && code->optlevel == 0)
-               jit_invalidate_code(m);
-}
-
-
-/* jit_get_current_code ********************************************************
-
-   Get the currently valid code for the given method. If there is no valid
-   code, (re)compile the method.
-
-   IN:
-       m................the method
-
-   RETURN VALUE:
-       the codeinfo* for the current code, or
-          NULL if an exception has been thrown during recompilation.
-
-*******************************************************************************/
-
-codeinfo *jit_get_current_code(methodinfo *m)
-{
-       assert(m);
-
-       /* if we have valid code, return it */
-
-       if (m->code && !code_is_invalid(m->code))
-               return m->code;
-
-       /* otherwise: recompile */
-
-       if (!jit_recompile(m))
-               return NULL;
-
-       assert(m->code);
-
-       return m->code;
-}
-
-
-/* jit_asm_compile *************************************************************
-
-   This method is called from asm_vm_call_method and does:
-
-     - create stackframe info for exceptions
-     - compile the method
-     - patch the entrypoint of the method into the calculated address in
-       the JIT code
-     - flushes the instruction cache.
-
-*******************************************************************************/
-
-#if defined(ENABLE_JIT)
-#if !defined(JIT_COMPILER_VIA_SIGNAL)
-u1 *jit_asm_compile(methodinfo *m, u1 *mptr, u1 *sp, u1 *ra)
-{
-       stackframeinfo_t  sfi;
-       u1               *entrypoint;
-       u1               *pa;
-       ptrint           *p;
-
-       /* create the stackframeinfo (subtract 1 from RA as it points to the */
-       /* instruction after the call)                                       */
-
-       stacktrace_stackframeinfo_add(&sfi, NULL, sp, ra, ra-1);
-
-       /* actually compile the method */
-
-       entrypoint = jit_compile(m);
-
-       /* remove the stackframeinfo */
-
-       stacktrace_stackframeinfo_remove(&sfi);
-
-       /* there was a problem during compilation */
-
-       if (entrypoint == NULL)
-               return NULL;
-
-       /* get the method patch address */
-
-       pa = md_jit_method_patch_address(sfi.pv, (void *) ra, mptr);
-
-       /* patch the method entry point */
-
-       p = (ptrint *) pa;
-
-       *p = (ptrint) entrypoint;
-
-       /* flush the instruction cache */
-
-       md_icacheflush(pa, SIZEOF_VOID_P);
-
-       return entrypoint;
-}
-#endif
-
-/* jit_compile_handle **********************************************************
-
-   This method is called from the appropriate signal handler which
-   handles compiler-traps and does the following:
-
-     - compile the method
-     - patch the entrypoint of the method into the calculated address in
-       the JIT code
-     - flush the instruction cache
-
-*******************************************************************************/
-
-void *jit_compile_handle(methodinfo *m, void *pv, void *ra, void *mptr)
-{
-       void      *newpv;                               /* new compiled method PV */
-       void      *pa;                                           /* patch address */
-       uintptr_t *p;                                      /* convenience pointer */
-
-       /* Compile the method. */
-
-       newpv = jit_compile(m);
-
-       /* There was a problem during compilation. */
-
-       if (newpv == NULL)
-               return NULL;
-
-       /* Get the method patch address. */
-
-       pa = md_jit_method_patch_address(pv, ra, mptr);
-
-       /* Patch the method entry point. */
-
-       p = (uintptr_t *) pa;
-
-       *p = (uintptr_t) newpv;
-
-       /* Flush both caches. */
-
-       md_cacheflush(pa, SIZEOF_VOID_P);
-
-       return newpv;
-}
-#endif /* defined(ENABLE_JIT) */
-
-
-/* jit_complement_condition ****************************************************
-
-   Returns the complement of the passed conditional instruction.
-
-   We use the order of the different conditions, e.g.:
-
-   ICMD_IFEQ         153
-   ICMD_IFNE         154
-
-   If the passed opcode is odd, we simply add 1 to get the complement.
-   If the opcode is even, we subtract 1.
-
-   Exception:
-
-   ICMD_IFNULL       198
-   ICMD_IFNONNULL    199
-
-*******************************************************************************/
-
-s4 jit_complement_condition(s4 opcode)
-{
-       switch (opcode) {
-       case ICMD_IFNULL:
-               return ICMD_IFNONNULL;
-
-       case ICMD_IFNONNULL:
-               return ICMD_IFNULL;
-
-       default:
-               /* check if opcode is odd */
-
-               if (opcode & 0x1)
-                       return opcode + 1;
-               else
-                       return opcode - 1;
-       }
-}
-
-
-/* jit_renumber_basicblocks ****************************************************
-
-   Set the ->nr of all blocks so it increases when traversing ->next.
-
-   IN:
-       jitdata..........the current jitdata
-
-*******************************************************************************/
-
-void jit_renumber_basicblocks(jitdata *jd)
-{
-       s4          nr;
-       basicblock *bptr;
-
-       nr = 0;
-       for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
-               bptr->nr = nr++;
-       }
-
-       /* we have one block more than jd->basicblockcount (the end marker) */
-
-       assert(nr == jd->basicblockcount + 1);
-}
-
-
-/* jit_check_basicblock_numbers ************************************************
-
-   Assert that the ->nr of the first block is zero and increases by 1 each
-   time ->next is traversed.
-   This function should be called before any analysis that relies on
-   the basicblock numbers.
-
-   IN:
-       jitdata..........the current jitdata
-
-   NOTE: Aborts with an assertion if the condition is not met!
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-void jit_check_basicblock_numbers(jitdata *jd)
-{
-       s4          nr;
-       basicblock *bptr;
-
-       nr = 0;
-       for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
-               assert(bptr->nr == nr);
-               nr++;
-       }
-
-       /* we have one block more than jd->basicblockcount (the end marker) */
-
-       assert(nr == jd->basicblockcount + 1);
-}
-#endif /* !defined(NDEBUG) */
-
-methoddesc *instruction_call_site(const instruction *iptr) {
-       if (iptr->opc == ICMD_BUILTIN) {
-               return iptr->sx.s23.s3.bte->md;
-       } else if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-               return iptr->sx.s23.s3.um->methodref->parseddesc.md;
-       } else {
-               return iptr->sx.s23.s3.fmiref->p.method->parseddesc;
-       }
-}
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
diff --git a/src/vm/jit/jit.cpp b/src/vm/jit/jit.cpp
new file mode 100644 (file)
index 0000000..e7dddde
--- /dev/null
@@ -0,0 +1,1197 @@
+/* src/vm/jit/jit.cpp - Just-In-Time compiler
+
+   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 "md.h"
+
+#include "mm/memory.h"
+
+#include "native/native.hpp"
+
+#include "toolbox/logging.h"
+
+#include "threads/mutex.hpp"
+
+#include "vm/class.h"
+#include "vm/global.h"
+#include "vm/globals.hpp"
+#include "vm/initialize.h"
+#include "vm/loader.hpp"
+#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/cfg.h"
+
+#include "vm/jit/codegen-common.hpp"
+#include "vm/jit/disass.h"
+#include "vm/jit/dseg.h"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/parse.h"
+#include "vm/jit/reg.h"
+
+#include "vm/jit/show.hpp"
+#include "vm/jit/stack.h"
+#include "vm/jit/stubs.hpp"
+
+#if defined(ENABLE_JITCACHE)
+# include "vm/jit/jitcache.hpp"
+#endif
+
+#if defined(ENABLE_OPAGENT)
+#include "vm/jit/oprofile-agent.hpp"
+#endif
+
+#include "vm/jit/allocator/simplereg.h"
+#if defined(ENABLE_LSRA) && !defined(ENABLE_SSA)
+# include "vm/jit/allocator/lsra.h"
+#endif
+
+#if defined(ENABLE_SSA)
+# include "vm/jit/optimizing/lsra.h"
+# include "vm/jit/optimizing/ssa.h"
+#endif
+
+#if defined(ENABLE_INLINING)
+# include "vm/jit/inline/inline.h"
+#endif
+
+#include "vm/jit/ir/bytecode.h"
+
+#include "vm/jit/loop/analyze.h"
+#include "vm/jit/loop/graph.h"
+#include "vm/jit/loop/loop.h"
+
+#if defined(ENABLE_IFCONV)
+# include "vm/jit/optimizing/ifconv.h"
+#endif
+
+#include "vm/jit/optimizing/reorder.h"
+
+#if defined(ENABLE_PYTHON)
+# include "vm/jit/python.h"
+#endif
+
+#include "vm/jit/verify/typecheck.h"
+
+
+/* debug macros ***************************************************************/
+
+#if !defined(NDEBUG)
+#define DEBUG_JIT_COMPILEVERBOSE(x)                            \
+    do {                                                                               \
+        if (compileverbose) {                                  \
+            log_message_method(x, m);                  \
+        }                                                                              \
+    } while (0)
+#else
+#define DEBUG_JIT_COMPILEVERBOSE(x)    /* nothing */
+#endif
+
+#if !defined(NDEBUG)
+# define TRACECOMPILERCALLS()                                                          \
+       do {                                                                                                    \
+               if (opt_TraceCompilerCalls) {                                           \
+                       log_start();                                                                    \
+                       log_print("[JIT compiler started: method=");    \
+                       method_print(m);                                                                \
+                       log_print("]");                                                                 \
+                       log_finish();                                                                   \
+               }                                                                                                       \
+       } while (0)
+#else
+# define TRACECOMPILERCALLS()
+#endif
+
+
+/* jit_init ********************************************************************
+
+   Initializes the JIT subsystem.
+
+*******************************************************************************/
+
+void jit_init(void)
+{
+       TRACESUBSYSTEMINITIALIZATION("jit_init");
+
+#if defined(ENABLE_JIT)
+       /* initialize stack analysis subsystem */
+
+       (void) stack_init();
+#endif
+
+       /* initialize show subsystem */
+
+#if !defined(NDEBUG)
+       (void) show_init();
+#endif
+
+       /* initialize codegen subsystem */
+
+       codegen_init();
+
+       /* initialize code subsystem */
+
+       (void) code_init();
+
+       /* Machine dependent initialization. */
+
+#if defined(ENABLE_JIT)
+# if defined(ENABLE_INTRP)
+       if (opt_intrp)
+               intrp_md_init();
+       else
+# endif
+               md_init();
+#else
+       intrp_md_init();
+#endif
+
+#if defined(ENABLE_OPAGENT)
+       if (opt_EnableOpagent)
+               OprofileAgent::initialize();
+#endif
+}
+
+
+/* jit_close *******************************************************************
+
+   Close the JIT subsystem.
+
+*******************************************************************************/
+
+void jit_close(void)
+{
+#if defined(ENABLE_OPAGENT)
+       if (opt_EnableOpagent)
+               OprofileAgent::close();
+#endif
+}
+
+
+/* dummy function, used when there is no JavaVM code available                */
+
+static u1 *do_nothing_function(void)
+{
+       return NULL;
+}
+
+
+/* jit_jitdata_new *************************************************************
+
+   Allocates and initalizes a new jitdata structure.
+
+*******************************************************************************/
+
+jitdata *jit_jitdata_new(methodinfo *m)
+{
+       jitdata  *jd;
+       codeinfo *code;
+
+       /* allocate jitdata structure and fill it */
+
+       jd = (jitdata*) DumpMemory::allocate(sizeof(jitdata));
+
+       jd->m     = m;
+       jd->cd    = (codegendata*) DumpMemory::allocate(sizeof(codegendata));
+       jd->rd    = (registerdata*) DumpMemory::allocate(sizeof(registerdata));
+#if defined(ENABLE_LOOP)
+       jd->ld    = (loopdata*) DumpMemory::allocate(sizeof(loopdata));
+#endif
+
+       /* Allocate codeinfo memory from the heap as we need to keep them. */
+
+       code = code_codeinfo_new(m);
+
+       /* Set codeinfo flags. */
+
+#if defined(ENABLE_THREADS)
+       if (checksync && (m->flags & ACC_SYNCHRONIZED))
+               code_flag_synchronized(code);
+
+       if (checksync && (m->flags & ACC_SYNCHRONIZED))
+               code_unflag_leafmethod(code);
+       else
+#endif
+               code_flag_leafmethod(code);
+
+       /* initialize variables */
+
+       jd->code                 = code;
+       jd->flags                = 0;
+       jd->exceptiontable       = NULL;
+       jd->exceptiontablelength = 0;
+       jd->returncount          = 0;
+       jd->branchtoentry        = false;
+       jd->branchtoend          = false;
+       jd->returncount          = 0;
+       jd->returnblock          = NULL;
+       jd->maxlocals            = m->maxlocals;
+
+       return jd;
+}
+
+
+/* jit_compile *****************************************************************
+
+   Translates one method to machine code.
+
+*******************************************************************************/
+
+static u1 *jit_compile_intern(jitdata *jd);
+
+u1 *jit_compile(methodinfo *m)
+{
+       u1      *r;
+       jitdata *jd;
+
+       STATISTICS(count_jit_calls++);
+
+       /* Initialize the static function's class. */
+
+       /* ATTENTION: This MUST be done before the method lock is aquired,
+          otherwise we could run into a deadlock with <clinit>'s that
+          call static methods of it's own class. */
+
+       if ((m->flags & ACC_STATIC) && !(m->clazz->state & CLASS_INITIALIZED)) {
+#if !defined(NDEBUG)
+               if (initverbose)
+                       log_message_class("Initialize class ", m->clazz);
+#endif
+
+               if (!initialize_class(m->clazz))
+                       return NULL;
+
+               /* check if the method has been compiled during initialization */
+
+               if ((m->code != NULL) && (m->code->entrypoint != NULL))
+                       return m->code->entrypoint;
+       }
+
+       /* enter a monitor on the method */
+
+       m->mutex->lock();
+
+       /* if method has been already compiled return immediately */
+
+       if (m->code != NULL) {
+               m->mutex->unlock();
+
+               assert(m->code->entrypoint);
+               return m->code->entrypoint;
+       }
+
+       TRACECOMPILERCALLS();
+
+       STATISTICS(count_methods++);
+
+#if defined (ENABLE_JITCACHE)
+
+       if (jitcache_load (m))
+       {
+               m->mutex->unlock();
+
+               return m->code->entrypoint;
+       }
+
+#endif
+
+#if defined(ENABLE_STATISTICS)
+       /* measure time */
+
+       if (opt_getcompilingtime)
+               compilingtime_start();
+#endif
+
+       // Create new dump memory area.
+       DumpMemoryArea dma;
+
+       /* create jitdata structure */
+
+       jd = jit_jitdata_new(m);
+
+       /* set the flags for the current JIT run */
+
+       jd->flags = JITDATA_FLAG_PARSE;
+
+#if defined(ENABLE_VERIFIER)
+       if (opt_verify)
+               jd->flags |= JITDATA_FLAG_VERIFY;
+#endif
+
+#if defined(ENABLE_PROFILING)
+       if (opt_prof)
+               jd->flags |= JITDATA_FLAG_INSTRUMENT;
+#endif
+
+#if defined(ENABLE_IFCONV)
+       if (opt_ifconv)
+               jd->flags |= JITDATA_FLAG_IFCONV;
+#endif
+
+#if defined(ENABLE_INLINING) && defined(ENABLE_INLINING_DEBUG)
+       if (opt_Inline && opt_InlineAll)
+               jd->flags |= JITDATA_FLAG_INLINE;
+#endif
+
+       if (opt_showintermediate)
+               jd->flags |= JITDATA_FLAG_SHOWINTERMEDIATE;
+
+       if (opt_showdisassemble)
+               jd->flags |= JITDATA_FLAG_SHOWDISASSEMBLE;
+
+       if (opt_verbosecall)
+               jd->flags |= JITDATA_FLAG_VERBOSECALL;
+
+#if defined(ENABLE_REPLACEMENT) && defined(ENABLE_INLINING)
+       if (opt_Inline && (jd->m->hitcountdown > 0) && (jd->code->optlevel == 0)) {
+               jd->flags |= JITDATA_FLAG_COUNTDOWN;
+       }
+#endif
+
+#if defined(ENABLE_JIT)
+# if defined(ENABLE_INTRP)
+       if (!opt_intrp)
+# endif
+               /* initialize the register allocator */
+       {
+               reg_setup(jd);
+       }
+#endif
+
+       /* setup the codegendata memory */
+
+       codegen_setup(jd);
+
+       /* now call internal compile function */
+
+       r = jit_compile_intern(jd);
+
+       if (r == NULL) {
+               /* We had an exception! Finish stuff here if necessary. */
+
+               /* release codeinfo */
+
+               code_codeinfo_free(jd->code);
+
+#if defined(ENABLE_PROFILING)
+               /* Release memory for basic block profiling information. */
+
+               if (JITDATA_HAS_FLAG_INSTRUMENT(jd))
+                       if (jd->code->bbfrequency != NULL)
+                               MFREE(jd->code->bbfrequency, u4, jd->code->basicblockcount);
+#endif
+       }
+       else {
+               DEBUG_JIT_COMPILEVERBOSE("Running: ");
+       }
+
+#if defined (ENABLE_JITCACHE)
+       jitcache_store(m);
+#endif
+
+#if defined(ENABLE_STATISTICS)
+       /* measure time */
+
+       if (opt_getcompilingtime)
+               compilingtime_stop();
+#endif
+
+#if defined(ENABLE_OPAGENT)
+       if (opt_EnableOpagent)
+               OprofileAgent::newmethod(m);
+#endif
+
+       /* leave the monitor */
+
+       m->mutex->unlock();
+
+       /* return pointer to the methods entry point */
+
+       return r;
+}
+
+
+/* jit_recompile ***************************************************************
+
+   Recompiles a Java method.
+
+*******************************************************************************/
+
+u1 *jit_recompile(methodinfo *m)
+{
+       u1      *r;
+       jitdata *jd;
+       u1       optlevel;
+
+       /* check for max. optimization level */
+
+       optlevel = (m->code) ? m->code->optlevel : 0;
+
+#if 0
+       if (optlevel == 1) {
+/*             log_message_method("not recompiling: ", m); */
+               return NULL;
+       }
+#endif
+
+       DEBUG_JIT_COMPILEVERBOSE("Recompiling start: ");
+
+       STATISTICS(count_jit_calls++);
+
+#if defined(ENABLE_STATISTICS)
+       /* measure time */
+
+       if (opt_getcompilingtime)
+               compilingtime_start();
+#endif
+
+       // Create new dump memory area.
+       DumpMemoryArea dma;
+
+       /* create jitdata structure */
+
+       jd = jit_jitdata_new(m);
+
+       /* set the current optimization level to the previous one plus 1 */
+
+       jd->code->optlevel = optlevel + 1;
+
+       /* get the optimization flags for the current JIT run */
+
+#if defined(ENABLE_VERIFIER)
+       jd->flags |= JITDATA_FLAG_VERIFY;
+#endif
+
+       /* jd->flags |= JITDATA_FLAG_REORDER; */
+       if (opt_showintermediate)
+               jd->flags |= JITDATA_FLAG_SHOWINTERMEDIATE;
+       if (opt_showdisassemble)
+               jd->flags |= JITDATA_FLAG_SHOWDISASSEMBLE;
+       if (opt_verbosecall)
+               jd->flags |= JITDATA_FLAG_VERBOSECALL;
+
+#if defined(ENABLE_INLINING)
+       if (opt_Inline)
+               jd->flags |= JITDATA_FLAG_INLINE;
+#endif
+
+#if defined(ENABLE_JIT)
+# if defined(ENABLE_INTRP)
+       if (!opt_intrp)
+# endif
+               /* initialize the register allocator */
+
+               reg_setup(jd);
+#endif
+
+       /* setup the codegendata memory */
+
+       codegen_setup(jd);
+
+       /* now call internal compile function */
+
+       r = jit_compile_intern(jd);
+
+       if (r == NULL) {
+               /* We had an exception! Finish stuff here if necessary. */
+
+               /* release codeinfo */
+
+               code_codeinfo_free(jd->code);
+       }
+
+#if defined(ENABLE_STATISTICS)
+       /* measure time */
+
+       if (opt_getcompilingtime)
+               compilingtime_stop();
+#endif
+
+#if defined(ENABLE_OPAGENT)
+       if (opt_EnableOpagent)
+               OprofileAgent::newmethod(m);
+#endif
+
+       DEBUG_JIT_COMPILEVERBOSE("Recompiling done: ");
+
+       /* return pointer to the methods entry point */
+
+       return r;
+}
+
+#if defined(ENABLE_PM_HACKS)
+#include "vm/jit/jit_pm_1.inc"
+#endif
+
+/* jit_compile_intern **********************************************************
+
+   Static internal function which does the actual compilation.
+
+*******************************************************************************/
+
+static u1 *jit_compile_intern(jitdata *jd)
+{
+       methodinfo  *m;
+       codegendata *cd;
+       codeinfo    *code;
+
+#if defined(ENABLE_RT_TIMING)
+       struct timespec time_start,time_checks,time_parse,time_stack,
+                                       time_typecheck,time_loop,time_ifconv,time_alloc,
+                                       time_codegen;
+#endif
+       
+       RT_TIMING_GET_TIME(time_start);
+
+       /* get required compiler data */
+
+#if defined(ENABLE_LSRA) || defined(ENABLE_SSA)
+       jd->ls = NULL;
+#endif
+       m    = jd->m;
+       code = jd->code;
+       cd   = jd->cd;
+       
+#if defined(ENABLE_DEBUG_FILTER)
+       show_filters_apply(jd->m);
+#endif
+
+       // Handle native methods and create a native stub.
+       if (m->flags & ACC_NATIVE) {
+               NativeMethods& nm = VM::get_current()->get_nativemethods();
+               void* f = nm.resolve_method(m);
+
+               if (f == NULL)
+                       return NULL;
+
+               code = NativeStub::generate(m, (functionptr) f);
+
+               /* Native methods are never recompiled. */
+               
+               assert(!m->code);
+
+               m->code = code;
+               
+               return code->entrypoint;
+       }
+
+       /* if there is no javacode, print error message and return empty method   */
+
+       if (m->jcode == NULL) {
+               DEBUG_JIT_COMPILEVERBOSE("No code given for: ");
+
+               code->entrypoint = (u1 *) (ptrint) do_nothing_function;
+               m->code = code;
+
+               return code->entrypoint;        /* return empty method                */
+       }
+
+#if defined(ENABLE_STATISTICS)
+       if (opt_stat) {
+               count_javacodesize += m->jcodelength + 18;
+               count_tryblocks    += jd->exceptiontablelength;
+               count_javaexcsize  += jd->exceptiontablelength * SIZEOF_VOID_P;
+       }
+#endif
+
+       RT_TIMING_GET_TIME(time_checks);
+
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+       /* Code for Sun's OpenJDK (see
+          hotspot/src/share/vm/classfile/verifier.cpp
+          (Verifier::is_eligible_for_verification)): Don't verify
+          dynamically-generated bytecodes. */
+
+# if defined(ENABLE_VERIFIER)
+       if (class_issubclass(m->clazz, class_sun_reflect_MagicAccessorImpl))
+               jd->flags &= ~JITDATA_FLAG_VERIFY;
+# endif
+#endif
+
+       /* call the compiler passes ***********************************************/
+
+       DEBUG_JIT_COMPILEVERBOSE("Parsing: ");
+
+       /* call parse pass */
+
+       if (!parse(jd)) {
+               DEBUG_JIT_COMPILEVERBOSE("Exception while parsing: ");
+
+               return NULL;
+       }
+       RT_TIMING_GET_TIME(time_parse);
+
+       DEBUG_JIT_COMPILEVERBOSE("Parsing done: ");
+       
+#if defined(ENABLE_JIT)
+# if defined(ENABLE_INTRP)
+       if (!opt_intrp) {
+# endif
+               DEBUG_JIT_COMPILEVERBOSE("Analysing: ");
+
+               /* call stack analysis pass */
+
+               if (!stack_analyse(jd)) {
+                       DEBUG_JIT_COMPILEVERBOSE("Exception while analysing: ");
+
+                       return NULL;
+               }
+               RT_TIMING_GET_TIME(time_stack);
+
+               DEBUG_JIT_COMPILEVERBOSE("Analysing done: ");
+
+#ifdef ENABLE_VERIFIER
+               if (JITDATA_HAS_FLAG_VERIFY(jd)) {
+                       DEBUG_JIT_COMPILEVERBOSE("Typechecking: ");
+
+                       /* call typecheck pass */
+                       if (!typecheck(jd)) {
+                               DEBUG_JIT_COMPILEVERBOSE("Exception while typechecking: ");
+
+                               return NULL;
+                       }
+
+                       DEBUG_JIT_COMPILEVERBOSE("Typechecking done: ");
+               }
+#endif
+               RT_TIMING_GET_TIME(time_typecheck);
+
+#if defined(ENABLE_LOOP)
+               if (opt_loops) {
+                       depthFirst(jd);
+                       analyseGraph(jd);
+                       optimize_loops(jd);
+                       jit_renumber_basicblocks(jd);
+               }
+#endif
+               RT_TIMING_GET_TIME(time_loop);
+
+#if defined(ENABLE_IFCONV)
+               if (JITDATA_HAS_FLAG_IFCONV(jd)) {
+                       if (!ifconv_static(jd))
+                               return NULL;
+                       jit_renumber_basicblocks(jd);
+               }
+#endif
+               RT_TIMING_GET_TIME(time_ifconv);
+
+               /* inlining */
+
+#if defined(ENABLE_INLINING) && (!defined(ENABLE_ESCAPE) || 1)
+               if (JITDATA_HAS_FLAG_INLINE(jd)) {
+                       if (!inline_inline(jd))
+                               return NULL;
+               }
+#endif
+
+#if defined(ENABLE_SSA)
+               if (opt_lsra) {
+                       fix_exception_handlers(jd);
+               }
+#endif
+
+               /* Build the CFG.  This has to be done after stack_analyse, as
+                  there happens the JSR elimination. */
+
+               if (!cfg_build(jd))
+                       return NULL;
+
+#if defined(ENABLE_PROFILING)
+               /* Basic block reordering.  I think this should be done after
+                  if-conversion, as we could lose the ability to do the
+                  if-conversion. */
+
+               if (JITDATA_HAS_FLAG_REORDER(jd)) {
+                       if (!reorder(jd))
+                               return NULL;
+                       jit_renumber_basicblocks(jd);
+               }
+#endif
+
+#if defined(ENABLE_PM_HACKS)
+#include "vm/jit/jit_pm_2.inc"
+#endif
+               DEBUG_JIT_COMPILEVERBOSE("Allocating registers: ");
+
+#if defined(ENABLE_LSRA) && !defined(ENABLE_SSA)
+               /* allocate registers */
+               if (opt_lsra) {
+                       if (!lsra(jd))
+                               return NULL;
+
+                       STATISTICS(count_methods_allocated_by_lsra++);
+
+               } else
+# endif /* defined(ENABLE_LSRA) && !defined(ENABLE_SSA) */
+#if defined(ENABLE_SSA)
+               /* allocate registers */
+               if (
+                       (opt_lsra &&
+                       jd->code->optlevel > 0) 
+                       /* strncmp(jd->m->name->text, "hottie", 6) == 0*/
+                       /*&& jd->exceptiontablelength == 0*/
+               ) {
+                       /*printf("=== %s ===\n", jd->m->name->text);*/
+                       jd->ls = (lsradata*) DumpMemory::allocate(sizeof(lsradata));
+                       jd->ls = NULL;
+                       ssa(jd);
+                       /*lsra(jd);*/ regalloc(jd);
+                       /*eliminate_subbasicblocks(jd);*/
+                       STATISTICS(count_methods_allocated_by_lsra++);
+
+               } else
+# endif /* defined(ENABLE_SSA) */
+               {
+                       STATISTICS(count_locals_conflicts += (jd->maxlocals - 1) * (jd->maxlocals));
+
+                       regalloc(jd);
+               }
+
+               STATISTICS(simplereg_make_statistics(jd));
+
+               DEBUG_JIT_COMPILEVERBOSE("Allocating registers done: ");
+# if defined(ENABLE_INTRP)
+       }
+# endif
+#endif /* defined(ENABLE_JIT) */
+       RT_TIMING_GET_TIME(time_alloc);
+
+#if defined(ENABLE_PROFILING)
+       /* Allocate memory for basic block profiling information. This
+          _must_ be done after loop optimization and register allocation,
+          since they can change the basic block count. */
+
+       if (JITDATA_HAS_FLAG_INSTRUMENT(jd))
+               code->bbfrequency = MNEW(u4, jd->basicblockcount);
+#endif
+
+       DEBUG_JIT_COMPILEVERBOSE("Generating code: ");
+
+       /* now generate the machine code */
+
+#if defined(ENABLE_JIT)
+# if defined(ENABLE_INTRP)
+       if (opt_intrp) {
+#if defined(ENABLE_VERIFIER)
+               if (opt_verify) {
+                       DEBUG_JIT_COMPILEVERBOSE("Typechecking (stackbased): ");
+
+                       if (!typecheck_stackbased(jd)) {
+                               DEBUG_JIT_COMPILEVERBOSE("Exception while typechecking (stackbased): ");
+                               return NULL;
+                       }
+               }
+#endif
+               if (!intrp_codegen(jd)) {
+                       DEBUG_JIT_COMPILEVERBOSE("Exception while generating code: ");
+
+                       return NULL;
+               }
+       } else
+# endif
+               {
+                       if (!codegen_generate(jd)) {
+                               DEBUG_JIT_COMPILEVERBOSE("Exception while generating code: ");
+
+                               return NULL;
+                       }
+               }
+#else
+       if (!intrp_codegen(jd)) {
+               DEBUG_JIT_COMPILEVERBOSE("Exception while generating code: ");
+
+               return NULL;
+       }
+#endif
+       RT_TIMING_GET_TIME(time_codegen);
+
+       DEBUG_JIT_COMPILEVERBOSE("Generating code done: ");
+
+#if !defined(NDEBUG) && defined(ENABLE_REPLACEMENT)
+       /* activate replacement points inside newly created code */
+
+       if (opt_TestReplacement)
+               replace_activate_replacement_points(code, false);
+#endif
+
+#if !defined(NDEBUG)
+#if defined(ENABLE_DEBUG_FILTER)
+       if (jd->m->filtermatches & SHOW_FILTER_FLAG_SHOW_METHOD)
+#endif
+       {
+               /* intermediate and assembly code listings */
+               
+               if (JITDATA_HAS_FLAG_SHOWINTERMEDIATE(jd)) {
+                       show_method(jd, SHOW_CODE);
+               }
+               else if (JITDATA_HAS_FLAG_SHOWDISASSEMBLE(jd)) {
+# if defined(ENABLE_DISASSEMBLER)
+                       DISASSEMBLE(code->entrypoint,
+                                               code->entrypoint + (code->mcodelength - cd->dseglen));
+# endif
+               }
+
+               if (opt_showddatasegment)
+                       dseg_display(jd);
+       }
+#endif
+
+       /* switch to the newly generated code */
+
+       assert(code);
+       assert(code->entrypoint);
+
+       /* add the current compile version to the methodinfo */
+
+       code->prev = m->code;
+       m->code = code;
+
+       RT_TIMING_TIME_DIFF(time_start,time_checks,RT_TIMING_JIT_CHECKS);
+       RT_TIMING_TIME_DIFF(time_checks,time_parse,RT_TIMING_JIT_PARSE);
+       RT_TIMING_TIME_DIFF(time_parse,time_stack,RT_TIMING_JIT_STACK);
+       RT_TIMING_TIME_DIFF(time_stack,time_typecheck,RT_TIMING_JIT_TYPECHECK);
+       RT_TIMING_TIME_DIFF(time_typecheck,time_loop,RT_TIMING_JIT_LOOP);
+       RT_TIMING_TIME_DIFF(time_loop,time_alloc,RT_TIMING_JIT_ALLOC);
+       RT_TIMING_TIME_DIFF(time_alloc,time_codegen,RT_TIMING_JIT_CODEGEN);
+       RT_TIMING_TIME_DIFF(time_start,time_codegen,RT_TIMING_JIT_TOTAL);
+
+       /* return pointer to the methods entry point */
+
+       return code->entrypoint;
+} 
+
+
+/* jit_invalidate_code *********************************************************
+
+   Mark the compiled code of the given method as invalid and take care that
+   it is replaced if necessary.
+
+   XXX Not fully implemented, yet.
+
+*******************************************************************************/
+
+void jit_invalidate_code(methodinfo *m)
+{
+       codeinfo *code;
+
+       code = m->code;
+
+       if (code == NULL || code_is_invalid(code))
+               return;
+
+       code_flag_invalid(code);
+
+       /* activate mappable replacement points */
+
+#if defined(ENABLE_REPLACEMENT)
+       replace_activate_replacement_points(code, true);
+#else
+       vm_abort("invalidating code only works with ENABLE_REPLACEMENT");
+#endif
+}
+
+
+/* jit_request_optimization ****************************************************
+
+   Request optimization of the given method. If the code of the method is
+   unoptimized, it will be invalidated, so the next jit_get_current_code(m)
+   triggers an optimized recompilation.
+   If the method is already optimized, this function does nothing.
+
+   IN:
+       m................the method
+
+*******************************************************************************/
+
+void jit_request_optimization(methodinfo *m)
+{
+       codeinfo *code;
+
+       code = m->code;
+
+       if (code && code->optlevel == 0)
+               jit_invalidate_code(m);
+}
+
+
+/* jit_get_current_code ********************************************************
+
+   Get the currently valid code for the given method. If there is no valid
+   code, (re)compile the method.
+
+   IN:
+       m................the method
+
+   RETURN VALUE:
+       the codeinfo* for the current code, or
+          NULL if an exception has been thrown during recompilation.
+
+*******************************************************************************/
+
+codeinfo *jit_get_current_code(methodinfo *m)
+{
+       assert(m);
+
+       /* if we have valid code, return it */
+
+       if (m->code && !code_is_invalid(m->code))
+               return m->code;
+
+       /* otherwise: recompile */
+
+       if (!jit_recompile(m))
+               return NULL;
+
+       assert(m->code);
+
+       return m->code;
+}
+
+
+/* jit_asm_compile *************************************************************
+
+   This method is called from asm_vm_call_method and does:
+
+     - create stackframe info for exceptions
+     - compile the method
+     - patch the entrypoint of the method into the calculated address in
+       the JIT code
+     - flushes the instruction cache.
+
+*******************************************************************************/
+
+#if defined(ENABLE_JIT)
+#if !defined(JIT_COMPILER_VIA_SIGNAL)
+extern "C" {
+void* jit_asm_compile(methodinfo *m, void* mptr, void* sp, void* ra)
+{
+       stackframeinfo_t  sfi;
+       void             *entrypoint;
+       void             *pa;
+       uintptr_t        *p;
+
+       /* create the stackframeinfo (subtract 1 from RA as it points to the */
+       /* instruction after the call)                                       */
+
+       stacktrace_stackframeinfo_add(&sfi, NULL, sp, ra, ((uint8_t*) ra) - 1);
+
+       /* actually compile the method */
+
+       entrypoint = jit_compile(m);
+
+       /* remove the stackframeinfo */
+
+       stacktrace_stackframeinfo_remove(&sfi);
+
+       /* there was a problem during compilation */
+
+       if (entrypoint == NULL)
+               return NULL;
+
+       /* get the method patch address */
+
+       pa = md_jit_method_patch_address(sfi.pv, (void *) ra, mptr);
+
+       /* patch the method entry point */
+
+       p = (uintptr_t*) pa;
+
+       *p = (uintptr_t) entrypoint;
+
+       /* flush the instruction cache */
+
+       md_icacheflush(pa, SIZEOF_VOID_P);
+
+       return entrypoint;
+}
+}
+#endif
+
+/* jit_compile_handle **********************************************************
+
+   This method is called from the appropriate signal handler which
+   handles compiler-traps and does the following:
+
+     - compile the method
+     - patch the entrypoint of the method into the calculated address in
+       the JIT code
+     - flush the instruction cache
+
+*******************************************************************************/
+
+void *jit_compile_handle(methodinfo *m, void *pv, void *ra, void *mptr)
+{
+       void      *newpv;                               /* new compiled method PV */
+       void      *pa;                                           /* patch address */
+       uintptr_t *p;                                      /* convenience pointer */
+
+       /* Compile the method. */
+
+       newpv = jit_compile(m);
+
+       /* There was a problem during compilation. */
+
+       if (newpv == NULL)
+               return NULL;
+
+       /* Get the method patch address. */
+
+       pa = md_jit_method_patch_address(pv, ra, mptr);
+
+       /* Patch the method entry point. */
+
+       p = (uintptr_t *) pa;
+
+       *p = (uintptr_t) newpv;
+
+       /* Flush both caches. */
+
+       md_cacheflush(pa, SIZEOF_VOID_P);
+
+       return newpv;
+}
+#endif /* defined(ENABLE_JIT) */
+
+
+/* jit_complement_condition ****************************************************
+
+   Returns the complement of the passed conditional instruction.
+
+   We use the order of the different conditions, e.g.:
+
+   ICMD_IFEQ         153
+   ICMD_IFNE         154
+
+   If the passed opcode is odd, we simply add 1 to get the complement.
+   If the opcode is even, we subtract 1.
+
+   Exception:
+
+   ICMD_IFNULL       198
+   ICMD_IFNONNULL    199
+
+*******************************************************************************/
+
+s4 jit_complement_condition(s4 opcode)
+{
+       switch (opcode) {
+       case ICMD_IFNULL:
+               return ICMD_IFNONNULL;
+
+       case ICMD_IFNONNULL:
+               return ICMD_IFNULL;
+
+       default:
+               /* check if opcode is odd */
+
+               if (opcode & 0x1)
+                       return opcode + 1;
+               else
+                       return opcode - 1;
+       }
+}
+
+
+/* jit_renumber_basicblocks ****************************************************
+
+   Set the ->nr of all blocks so it increases when traversing ->next.
+
+   IN:
+       jitdata..........the current jitdata
+
+*******************************************************************************/
+
+void jit_renumber_basicblocks(jitdata *jd)
+{
+       s4          nr;
+       basicblock *bptr;
+
+       nr = 0;
+       for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
+               bptr->nr = nr++;
+       }
+
+       /* we have one block more than jd->basicblockcount (the end marker) */
+
+       assert(nr == jd->basicblockcount + 1);
+}
+
+
+/* jit_check_basicblock_numbers ************************************************
+
+   Assert that the ->nr of the first block is zero and increases by 1 each
+   time ->next is traversed.
+   This function should be called before any analysis that relies on
+   the basicblock numbers.
+
+   IN:
+       jitdata..........the current jitdata
+
+   NOTE: Aborts with an assertion if the condition is not met!
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void jit_check_basicblock_numbers(jitdata *jd)
+{
+       s4          nr;
+       basicblock *bptr;
+
+       nr = 0;
+       for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
+               assert(bptr->nr == nr);
+               nr++;
+       }
+
+       /* we have one block more than jd->basicblockcount (the end marker) */
+
+       assert(nr == jd->basicblockcount + 1);
+}
+#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:
+ */
diff --git a/src/vm/jit/jit.h b/src/vm/jit/jit.h
deleted file mode 100644 (file)
index 6744106..0000000
+++ /dev/null
@@ -1,1064 +0,0 @@
-/* src/vm/jit/jit.h - code generation 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 _JIT_H
-#define _JIT_H
-
-/* forward typedefs ***********************************************************/
-
-typedef struct jitdata jitdata;
-typedef struct basicblock basicblock;
-typedef struct instruction instruction;
-typedef struct insinfo_inline insinfo_inline;
-typedef struct exception_entry exception_entry;
-
-
-#include "config.h"
-#include "vm/types.h"
-
-#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/stack.h"
-#include "vm/jit/stacktrace.hpp"
-
-#if defined(ENABLE_INLINING)
-# include "vm/jit/inline/inline.h"
-#endif
-
-#include "vm/jit/ir/bytecode.h"
-
-#if defined(ENABLE_LOOP)
-# include "vm/jit/loop/loop.h"
-#endif
-#if defined(ENABLE_SSA) 
-# include "vm/jit/optimizing/lsra.h"
-#endif
-#if defined(ENABLE_LSRA)
-# include "vm/jit/allocator/lsra.h"
-#endif
-
-#include "vm/jit/verify/typeinfo.h"
-
-
-/* common jit/codegen macros **************************************************/
-
-#if defined(ENABLE_STATISTICS)
-# define COUNT(x)        (x)++
-# define COUNT_SPILLS             /* use COUNT_(READ|WRITE)_SPILLS instead */
-# define COUNT_READ_SPILLS(var) \
-       switch(var->type) { \
-       case TYPE_FLT: count_spills_read_flt++; break; \
-       case TYPE_DBL: count_spills_read_dbl++; break; \
-       default: count_spills_read_ila++; break; \
-       }
-
-# define COUNT_WRITE_SPILLS(var) \
-       switch(var->type) { \
-       case TYPE_FLT: count_spills_write_flt++; break; \
-       case TYPE_DBL: count_spills_write_dbl++; break; \
-       default: count_spills_write_ila++; break; \
-       }
-
-#else
-# define COUNT(x)                /* nothing */
-# define COUNT_SPILLS            /* nothing */
-# define COUNT_READ_SPILLS(x)    /* nothing */
-# define COUNT_WRITE_SPILLS(x)   /* nothing */
-#endif
-
-typedef struct interface_info interface_info;
-
-struct interface_info {
-       s4 flags;
-       s4 regoff;
-};
-
-
-/* jitdata ********************************************************************/
-
-struct jitdata {
-       methodinfo      *m;               /* methodinfo of the method compiled    */
-       codeinfo        *code;
-       codegendata     *cd;
-       registerdata    *rd;
-#if defined(ENABLE_LOOP)
-       loopdata        *ld;
-#endif
-#if defined(ENABLE_SSA) || defined(ENABLE_LSRA)
-       lsradata        *ls;
-#endif
-
-       u4               flags;           /* contains JIT compiler flags          */
-
-       instruction     *instructions;    /* ICMDs, valid between parse and stack */
-       basicblock      *basicblocks;     /* start of basic block list            */
-       stackelement_t  *stack;           /* XXX should become stack.c internal   */
-       s4               instructioncount;/* XXX remove this?                     */
-       s4               basicblockcount; /* number of basic blocks               */
-       s4               stackcount;      /* number of stackelements to allocate  */
-                                      /* (passed from parse to stack)         */
-
-       varinfo         *var;             /* array of variables                   */
-       s4               vartop;          /* next free index in var array         */
-
-       s4               varcount;        /* number of variables in var array     */
-       s4               localcount;      /* number of locals at start of var ar. */
-    s4              *local_map;       /* map for renaming (de-coallescing)    */
-                                        /* locals and keeping the coalescing info for simplereg. */
-                        /* local_map[javaindex * 5 + type] =                     */
-                        /*     >= 0......index into jd->var, or                  */
-                                        /*     UNUSED....this (javaindex,type) pair is not used  */
-
-       s4              *reverselocalmap; /* map from CACAO varindex to javaindex */
-                                         /* (varindex must be < localcount)      */
-
-       s4               maxlocals;       /* max. number of javalocals            */
-
-       interface_info  *interface_map;   /* interface variables (for simplereg)  */
-       s4               maxinterfaces;   /* max. number of interface variables   */
-
-       s4               exceptiontablelength; /* exceptiontable length           */
-       exception_entry *exceptiontable;       /* the exceptiontable              */
-
-       basicblock      *returnblock;          /* block containing the *RETURN    */
-                                              /* (only use if returncount==1)    */
-       s4               returncount;          /* number of return instructions   */
-       bool             branchtoentry;        /* true if first block is a target */
-       bool             branchtoend;          /* true if end dummy is a target   */
-};
-
-#define FOR_EACH_BASICBLOCK(jd, it) \
-       for ((it) = (jd)->basicblocks; (it) != NULL; (it) = (it)->next)
-
-#define UNUSED                     -1
-
-#define JITDATA_FLAG_PARSE               0x00000001
-#define JITDATA_FLAG_VERIFY              0x00000002
-
-#define JITDATA_FLAG_INSTRUMENT          0x00000004
-
-#define JITDATA_FLAG_IFCONV              0x00000008
-#define JITDATA_FLAG_REORDER             0x00000010
-#define JITDATA_FLAG_INLINE              0x00000020
-
-#define JITDATA_FLAG_COUNTDOWN           0x00000100
-
-#define JITDATA_FLAG_SHOWINTERMEDIATE    0x20000000
-#define JITDATA_FLAG_SHOWDISASSEMBLE     0x40000000
-#define JITDATA_FLAG_VERBOSECALL         0x80000000
-
-
-#define JITDATA_HAS_FLAG_PARSE(jd) \
-    ((jd)->flags & JITDATA_FLAG_PARSE)
-
-#define JITDATA_HAS_FLAG_VERIFY(jd) \
-    ((jd)->flags & JITDATA_FLAG_VERIFY)
-
-#define JITDATA_HAS_FLAG_INSTRUMENT(jd) \
-    ((jd)->flags & JITDATA_FLAG_INSTRUMENT)
-
-#define JITDATA_HAS_FLAG_IFCONV(jd) \
-    ((jd)->flags & JITDATA_FLAG_IFCONV)
-
-#define JITDATA_HAS_FLAG_REORDER(jd) \
-    ((jd)->flags & JITDATA_FLAG_REORDER)
-
-#define JITDATA_HAS_FLAG_INLINE(jd) \
-    ((jd)->flags & JITDATA_FLAG_INLINE)
-
-#define JITDATA_HAS_FLAG_COUNTDOWN(jd) \
-    ((jd)->flags & JITDATA_FLAG_COUNTDOWN)
-
-#define JITDATA_HAS_FLAG_SHOWINTERMEDIATE(jd) \
-    ((jd)->flags & JITDATA_FLAG_SHOWINTERMEDIATE)
-
-#define JITDATA_HAS_FLAG_SHOWDISASSEMBLE(jd) \
-    ((jd)->flags & JITDATA_FLAG_SHOWDISASSEMBLE)
-
-#define JITDATA_HAS_FLAG_VERBOSECALL(jd) \
-    ((jd)->flags & JITDATA_FLAG_VERBOSECALL)
-
-
-/* exception_entry ************************************************************/
-
-struct exception_entry {
-       basicblock           *start;
-       basicblock           *end;
-       basicblock           *handler;
-       classref_or_classinfo catchtype; /* catchtype of exc. (NULL == catchall)  */
-       exception_entry      *next;      /* next in list of exceptions when       */
-                                                                        /* loops are copied                      */
-       exception_entry      *down;      /* next exception_entry                  */
-};
-
-
-/* macros for accessing variables *********************************************
-   Use VAROP for s1, s2, s3 and dst operands (eg. VAROP(iptr->s1)),
-   use VAR if you have the variable index (eg. VAR(iptr->sx.s23.s2.args[0])).
-
-******************************************************************************/
-
-#define VAROP(v) (jd->var + (v).varindex)
-#define VAR(i)   (jd->var + (i))
-
-static inline bool var_is_local(const jitdata *jd, s4 i) {
-       return (i < jd->localcount);
-}
-
-static inline bool var_is_prealloc(const jitdata *jd, s4 i) {
-       return ((i >= jd->localcount) && (jd->var[i].flags & PREALLOC));
-}
-
-static inline bool var_is_inout(const jitdata *jd, s4 i) {
-       const varinfo *v = jd->var + i;
-       return (
-               (i >= jd->localcount) && (
-                       (!(v->flags & PREALLOC) && (v->flags & INOUT)) ||
-                       /* special case of TYPE_RET, used with JSR */
-                       ((v->flags & PREALLOC) && (v->flags & INOUT) && (v->type == TYPE_RET))
-               )
-       );
-}
-
-static inline bool var_is_temp(const jitdata *jd, s4 i) {
-       const varinfo *v = jd->var + i;
-       return ((i >= jd->localcount) && !(v->flags & PREALLOC) && !(v->flags & INOUT));
-}
-
-static inline bool var_is_saved(const jitdata *jd, s4 i) {
-       return (jd->var[i].flags & SAVEDVAR);
-}
-
-
-/**************************** instruction structure ***************************/
-
-/* branch_target_t: used in TABLESWITCH tables */
-
-typedef union {
-    s4                         insindex; /* used in parse                     */
-    basicblock                *block;    /* valid after parse                 */
-} branch_target_t;
-
-/* lookup_target_t: used in LOOKUPSWITCH tables */
-
-typedef struct {
-    s4                         value;    /* case value                        */
-    branch_target_t            target;   /* branch target, see above          */
-} lookup_target_t;
-
-/*** s1 operand ***/
-
-typedef union {
-       s4                         varindex;
-    s4                         argcount;
-} s1_operand_t;
-
-/*** s2 operand ***/
-
-typedef union {
-       s4                         varindex;
-       s4                        *args;
-    classref_or_classinfo      c;
-    unresolved_class          *uc;
-    ptrint                     constval;         /* for PUT*CONST             */
-    s4                         tablelow;         /* for TABLESWITCH           */
-    u4                         lookupcount;      /* for LOOKUPSWITCH          */
-       s4                         retaddrnr;        /* for ASTORE                */
-       instruction              **iargs;            /* for PHI                   */
-} s2_operand_t;
-
-/*** s3 operand ***/
-
-typedef union {
-       s4                         varindex;
-    ptrint                     constval;
-    classref_or_classinfo      c;
-    constant_FMIref           *fmiref;
-    unresolved_method         *um;
-    unresolved_field          *uf;
-    insinfo_inline            *inlineinfo;       /* for INLINE_START/END      */
-    s4                         tablehigh;        /* for TABLESWITCH           */
-    branch_target_t            lookupdefault;    /* for LOOKUPSWITCH          */
-    branch_target_t            jsrtarget;        /* for JSR                   */
-       s4                         javaindex;        /* for *STORE                */
-    struct builtintable_entry *bte;
-} s3_operand_t;
-
-/*** val operand ***/
-
-typedef union {
-    s4                        i;
-    s8                        l;
-    float                     f;
-    double                    d;
-    void                     *anyptr;
-    java_handle_t            *stringconst;       /* for ACONST with string    */
-    classref_or_classinfo     c;                 /* for ACONST with class     */
-} val_operand_t;
-
-/*** dst operand ***/
-
-typedef union {
-       s4                         varindex;
-    basicblock                *block;       /* valid after parse              */
-    branch_target_t           *table;       /* for TABLESWITCH                */
-    lookup_target_t           *lookup;      /* for LOOKUPSWITCH               */
-    s4                         insindex;    /* used in parse                  */
-} dst_operand_t;
-
-/*** flags (32 bits) ***/
-
-#define INS_FLAG_BASICBLOCK    0x01    /* marks a basic block start           */
-#define INS_FLAG_UNRESOLVED    0x02    /* contains unresolved field/meth/class*/
-#define INS_FLAG_CLASS         0x04    /* for ACONST, PUT*CONST with class    */
-#define INS_FLAG_ARRAY         0x08    /* for CHECKCAST/INSTANCEOF with array */
-#define INS_FLAG_CHECK         0x10    /* for *ALOAD|*ASTORE: check index     */
-                                       /* for BUILTIN: check exception        */
-#define INS_FLAG_KILL_PREV     0x04    /* for *STORE, invalidate prev local   */
-#define INS_FLAG_KILL_NEXT     0x08    /* for *STORE, invalidate next local   */
-#define INS_FLAG_RETADDR       0x10    /* for ASTORE: op is a returnAddress   */
-
-#define INS_FLAG_ID_SHIFT      5
-#define INS_FLAG_ID_MASK       (~0 << INS_FLAG_ID_SHIFT)
-
-typedef union {
-    u4                  bits;
-} flags_operand_t;
-
-/*** instruction ***/
-
-/* The instruction format for the intermediate representation: */
-
-struct instruction {
-    u2                      opc;    /* opcode       */
-    u2                      line;   /* line number  */
-#if SIZEOF_VOID_P == 8
-    flags_operand_t         flags;  /* 4 bytes      */
-#endif
-    s1_operand_t            s1;     /* pointer-size */
-    union {
-        struct {
-            s2_operand_t    s2;     /* pointer-size */
-            s3_operand_t    s3;     /* pointer-size */
-        } s23;                      /*     XOR      */
-        val_operand_t       val;    /*  long-size   */
-    } sx;
-    dst_operand_t           dst;    /* pointer-size */
-#if SIZEOF_VOID_P == 4
-    flags_operand_t         flags;  /* 4 bytes      */
-#endif
-#if defined(ENABLE_ESCAPE_REASON)
-       void *escape_reasons;
-#endif
-};
-
-
-#define INSTRUCTION_STARTS_BASICBLOCK(iptr) \
-       ((iptr)->flags.bits & INS_FLAG_BASICBLOCK)
-
-#define INSTRUCTION_IS_RESOLVED(iptr) \
-       (!((iptr)->flags.bits & INS_FLAG_UNRESOLVED))
-
-#define INSTRUCTION_IS_UNRESOLVED(iptr) \
-       ((iptr)->flags.bits & INS_FLAG_UNRESOLVED)
-
-#define INSTRUCTION_MUST_CHECK(iptr) \
-       ((iptr)->flags.bits & INS_FLAG_CHECK)
-
-#define INSTRUCTION_GET_FIELDREF(iptr,fref) \
-       do { \
-               if (iptr->flags.bits & INS_FLAG_UNRESOLVED) \
-                       fref = iptr->sx.s23.s3.uf->fieldref; \
-               else \
-                       fref = iptr->sx.s23.s3.fmiref; \
-       } while (0)
-
-#define INSTRUCTION_GET_METHODREF(iptr,mref) \
-       do { \
-               if (iptr->flags.bits & INS_FLAG_UNRESOLVED) \
-                       mref = iptr->sx.s23.s3.um->methodref; \
-               else \
-                       mref = iptr->sx.s23.s3.fmiref; \
-       } while (0)
-
-#define INSTRUCTION_GET_METHODDESC(iptr, md) \
-       do { \
-               if (iptr->flags.bits & INS_FLAG_UNRESOLVED) \
-                       md = iptr->sx.s23.s3.um->methodref->parseddesc.md; \
-               else \
-                       md = iptr->sx.s23.s3.fmiref->parseddesc.md; \
-       } while (0)
-
-/* additional info structs for special instructions ***************************/
-
-/* for ICMD_INLINE_START and ICMD_INLINE_END */
-
-struct insinfo_inline {
-       /* fields copied from the inlining tree ----------------------------------*/
-       insinfo_inline *parent;     /* insinfo of the surrounding inlining, if any*/
-       methodinfo     *method;     /* the inlined method starting/ending here    */
-       methodinfo     *outer;      /* the outer method suspended/resumed here    */
-       s4              synclocal;      /* local index used for synchronization   */
-       bool            synchronize;    /* true if synchronization is needed      */
-       s4              throughcount;   /* total # of pass-through variables      */
-       s4              paramcount;     /* number of parameters of original call  */
-       s4              stackvarscount; /* source stackdepth at INLINE_START      */
-       s4             *stackvars;      /* stack vars at INLINE_START             */
-
-       /* fields set by inlining ------------------------------------------------*/
-       s4         *javalocals_start; /* javalocals at start of inlined body      */
-       s4         *javalocals_end;   /* javalocals after inlined body            */
-
-       /* fields set by replacement point creation ------------------------------*/
-#if defined(ENABLE_REPLACEMENT)
-       rplpoint   *rp;             /* replacement point at INLINE_START          */
-#endif
-
-       /* fields set by the codegen ---------------------------------------------*/
-       s4          startmpc;       /* machine code offset of start of inlining   */
-};
-
-
-/* basicblock *****************************************************************/
-
-/* flags */
-
-#define BBDELETED            -2
-#define BBUNDEF              -1
-#define BBREACHED            0
-#define BBFINISHED           1
-
-#define BBTYPECHECK_UNDEF    2
-#define BBTYPECHECK_REACHED  3
-
-#define BBTYPE_STD           0  /* standard basic block type                  */
-#define BBTYPE_EXH           1  /* exception handler basic block type         */
-#define BBTYPE_SBR           2  /* subroutine basic block type                */
-
-#define BBFLAG_REPLACEMENT   0x01  /* put a replacement point at the start    */
-
-/* XXX basicblock wastes quite a lot of memory by having four flag fields     */
-/* (flags, bitflags, type and lflags). Probably the last three could be       */
-/* combined without loss of efficiency. The first one could be combined with  */
-/* the others by using bitfields.                                             */
-
-/* XXX "flags" should probably be called "state", as it is an integer state   */
-
-struct basicblock {
-       s4            nr;           /* basic block number                         */
-       s4            flags;        /* used during stack analysis, init with -1   */
-       s4            bitflags;     /* OR of BBFLAG_... constants, init with 0    */
-       s4            type;         /* basic block type (std, xhandler, subroutine*/
-       s4            lflags;       /* used during loop copying, init with 0      */
-
-       s4            icount;       /* number of intermediate code instructions   */
-       instruction  *iinstr;       /* pointer to intermediate code instructions  */
-
-       varinfo      *inlocals;     /* copy of locals on block entry              */
-       s4           *javalocals;   /* map from java locals to cacao variables[+] */
-       s4           *invars;       /* array of in-variables at begin of block    */
-       s4           *outvars;      /* array of out-variables at end of block     */
-       s4            indepth;      /* stack depth at begin of basic block        */
-       s4            outdepth;     /* stack depth end of basic block             */
-       s4            varstart;     /* index of first non-invar block variable    */
-       s4            varcount;     /* number of non-invar block variables        */
-
-       s4            predecessorcount;
-       s4            successorcount;
-       basicblock  **predecessors; /* array of predecessor basic blocks          */
-       basicblock  **successors;   /* array of successor basic blocks            */
-
-       branchref    *branchrefs;   /* list of branches to be patched             */
-
-       basicblock   *next;         /* used to build a BB list (instead of array) */
-       basicblock   *copied_to;    /* points to the copy of this basic block     */
-                                /* when loop nodes are copied                 */
-       basicblock   *original;     /* block of which this block is a clone       */
-                                   /* NULL for the original block itself         */
-       methodinfo   *method;       /* method this block belongs to               */
-       insinfo_inline *inlineinfo; /* inlineinfo for the start of this block     */
-
-       s4            mpc;          /* machine code pc at start of block          */
-
-       /* TODO: those fields are probably usefull for other passes as well. */
-
-#if defined(ENABLE_SSA)         
-       basicblock   *idom;         /* Immediate dominator, parent in dominator tree */
-       basicblock  **domsuccessors;/* Children in dominator tree                 */
-       s4            domsuccessorcount;
-
-       basicblock  **domfrontier;  /* Dominance frontier                         */
-       s4            domfrontiercount;
-
-       basicblock  **exhandlers;   /* Exception handlers for this block */
-       s4            exhandlercount;
-       basicblock  **expredecessors; /* Blocks this block is exception handler for */
-       s4            expredecessorcount;
-       s4            exouts;       /* Number of exceptional exits */
-
-       instruction  *phis;         /* Phi functions */
-       s4            phicount;     /* Number of phi functions */
-
-       void         *vp;           /* Freely used by different passes            */
-#endif
-};
-
-#define FOR_EACH_SUCCESSOR(bptr, it) \
-       for ((it) = (bptr)->successors; (it) != (bptr)->successors + (bptr)->successorcount; ++(it))
-
-#define FOR_EACH_PREDECESSOR(bptr, it) \
-       for ( \
-               (it) = (bptr)->predecessors; \
-               (it) != (bptr)->predecessors + ((bptr)->predecessorcount < 0 ? 0 : (bptr)->predecessorcount); \
-               ++(it) \
-       )
-
-#define FOR_EACH_INSTRUCTION(bptr, it) \
-       for ((it) = (bptr)->iinstr; (it) != (bptr)->iinstr + (bptr)->icount; ++(it))
-
-#define FOR_EACH_INSTRUCTION_REV(bptr, it) \
-       for ((it) = (bptr)->iinstr + (bptr)->icount - 1; (it) != (bptr)->iinstr - 1; --(it))
-
-#if defined(ENABLE_SSA)
-
-#define FOR_EACH_EXHANDLER(bptr, it) \
-       for ((it) = (bptr)->exhandlers; (it) != (bptr)->exhandlers + (bptr)->exhandlercount; ++(it))
-
-#define FOR_EACH_EXPREDECESSOR(bptr, it) \
-       for ((it) = (bptr)->expredecessors; (it) != (bptr)->expredecessors + (bptr)->expredecessorcount; ++(it))
-
-#endif
-
-/* [+]...the javalocals array: This array is indexed by the javaindex (the    */
-/*       local variable index ocurring in the original bytecode). An element  */
-/*       javalocals[javaindex] encodes where to find the contents of the      */
-/*       original variable at this point in the program.                      */
-/*       There are three cases for javalocals[javaindex]:                     */
-/*           >= 0.......it's an index into the jd->var array, where the       */
-/*                      CACAO variable corresponding to the original local    */
-/*                      can be found.                                         */
-/*           UNUSED.....the original variable is not live at this point       */
-/*           < UNUSED...the original variable contains a returnAddress at     */
-/*                      this point. The number of the block to return to can  */
-/*                      be calculated using RETADDR_FROM_JAVALOCAL:           */
-/*                                                                            */
-/*                      javalocals[javaindex] == JAVALOCAL_FROM_RETADDR(nr)   */
-/*                      RETADDR_FROM_JAVALOCAL(javalocals[javaindex]) == nr   */
-
-#define JAVALOCAL_FROM_RETADDR(nr)  (UNUSED - (1 + (nr)))
-#define RETADDR_FROM_JAVALOCAL(jl)  (UNUSED - (1 + (jl)))
-
-
-/* Macro for initializing newly allocated basic block's. It does not
-   need to zero fields, as we zero out the whole basic block array. */
-
-#define BASICBLOCK_INIT(bptr,m)                        \
-       do {                                               \
-               bptr->mpc    = -1;                             \
-               bptr->flags  = -1;                             \
-               bptr->type   = BBTYPE_STD;                     \
-               bptr->method = (m);                            \
-       } while (0)
-
-static inline bool basicblock_reached(const basicblock *bptr) {
-       return (bptr->flags >= BBREACHED);
-}
-
-/* data-flow constants for the ICMD table ************************************/
-
-#define DF_0_TO_0      0
-#define DF_1_TO_0      1
-#define DF_2_TO_0      2
-#define DF_3_TO_0      3
-
-#define DF_DST_BASE    4      /* from this value on, iptr->dst is a variable */
-
-#define DF_0_TO_1      (DF_DST_BASE + 0)
-#define DF_1_TO_1      (DF_DST_BASE + 1)
-#define DF_2_TO_1      (DF_DST_BASE + 2)
-#define DF_3_TO_1      (DF_DST_BASE + 3)
-#define DF_N_TO_1      (DF_DST_BASE + 4)
-
-#define DF_INVOKE      (DF_DST_BASE + 5)
-#define DF_BUILTIN     (DF_DST_BASE + 6)
-
-#define DF_COPY        (DF_DST_BASE + 7)
-#define DF_MOVE        (DF_DST_BASE + 8)
-
-#define DF_DUP         -1
-#define DF_DUP_X1      -1
-#define DF_DUP_X2      -1
-#define DF_DUP2        -1
-#define DF_DUP2_X1     -1
-#define DF_DUP2_X2     -1
-#define DF_SWAP        -1
-
-/* special data-flow recognized by verify/generate.pl: */
-#define DF_LOAD        DF_COPY
-#define DF_STORE       DF_MOVE
-#define DF_IINC        DF_1_TO_1
-#define DF_POP         DF_1_TO_0
-#define DF_POP2        DF_2_TO_0
-
-
-/* control-flow constants for the ICMD table *********************************/
-
-#define CF_NORMAL      0
-#define CF_IF          1
-
-#define CF_END_BASE    2  /* from here on, they mark the end of a superblock */
-
-#define CF_END         (CF_END_BASE + 0)
-#define CF_GOTO        (CF_END_BASE + 1)
-#define CF_TABLE       (CF_END_BASE + 2)
-#define CF_LOOKUP      (CF_END_BASE + 3)
-#define CF_JSR         (CF_END_BASE + 4)
-#define CF_RET         (CF_END_BASE + 5)
-
-
-/* flag constants for the ICMD table *****************************************/
-
-#define ICMDTABLE_PEI    0x0001               /* ICMD may throw an exception */
-#define ICMDTABLE_CALLS  0x0002     /* needs registers to be saved, may call */
-
-
-/* ICMD table entry **********************************************************/
-
-typedef struct icmdtable_entry_t icmdtable_entry_t;
-
-struct icmdtable_entry_t {
-#if !defined(NDEBUG)
-       char *name;                                /* name, without ICMD_ prefix */
-#endif
-       s4    dataflow;                             /* a DF_ constant, see above */
-       s4    controlflow;                          /* a CF_ constant, see above */
-       s4    flags;                        /* a combination of ICMDTABLE_ flags */
-};
-
-
-/* the ICMD table ************************************************************/
-
-extern icmdtable_entry_t icmd_table[256];
-
-
-/********** JavaVM operation codes (sorted) and instruction lengths ***********/
-
-enum {
-       ICMD_NOP               = BC_nop,
-
-       ICMD_ACONST            = BC_aconst_null,
-
-       ICMD_CHECKNULL         = 2,
-
-       ICMD_ICONST            = BC_iconst_0,
-
-       /* 3 */
-       /* 4 */
-
-       ICMD_IDIVPOW2          = 5,
-       ICMD_LDIVPOW2          = 6,
-
-       /* 7 */
-       /* 8 */
-
-       ICMD_LCONST            = BC_lconst_0,
-
-       ICMD_LCMPCONST         = 10,
-
-       ICMD_FCONST            = BC_fconst_0,
-
-       /* 12 */
-       /* 13 */
-
-       ICMD_DCONST            = BC_dconst_0,
-
-       ICMD_COPY              = 15,
-       ICMD_MOVE              = 16,
-
-       /* 17 */
-       /* 18 */
-       /* 19 */
-       /* 20 */
-
-       /* Order of LOAD instructions must be equal to order of TYPE_*
-          defines. */
-
-       ICMD_ILOAD            = BC_iload,
-       ICMD_LLOAD            = BC_lload,
-       ICMD_FLOAD            = BC_fload,
-       ICMD_DLOAD            = BC_dload,
-       ICMD_ALOAD            = BC_aload,
-
-       ICMD_IADDCONST        = 26,
-       ICMD_ISUBCONST        = 27,
-       ICMD_IMULCONST        = 28,
-       ICMD_IANDCONST        = 29,
-       ICMD_IORCONST         = 30,
-       ICMD_IXORCONST        = 31,
-
-       ICMD_ISHLCONST        = 32,
-       ICMD_ISHRCONST        = 33,
-       ICMD_IUSHRCONST       = 34,
-
-       ICMD_IREMPOW2         = 35,
-
-       ICMD_LADDCONST        = 36,
-       ICMD_LSUBCONST        = 37,
-       ICMD_LMULCONST        = 38,
-       ICMD_LANDCONST        = 39,
-       ICMD_LORCONST         = 40,
-       ICMD_LXORCONST        = 41,
-
-       ICMD_LSHLCONST        = 42,
-       ICMD_LSHRCONST        = 43,
-       ICMD_LUSHRCONST       = 44,
-
-       ICMD_LREMPOW2         = 45,
-
-       ICMD_IALOAD           = BC_iaload,
-       ICMD_LALOAD           = BC_laload,
-       ICMD_FALOAD           = BC_faload,
-       ICMD_DALOAD           = BC_daload,
-       ICMD_AALOAD           = BC_aaload,
-       ICMD_BALOAD           = BC_baload,
-       ICMD_CALOAD           = BC_caload,
-       ICMD_SALOAD           = BC_saload,
-
-       /* Order of STORE instructions must be equal to order of TYPE_*
-          defines. */
-
-       ICMD_ISTORE           = BC_istore,
-       ICMD_LSTORE           = BC_lstore,
-       ICMD_FSTORE           = BC_fstore,
-       ICMD_DSTORE           = BC_dstore,
-       ICMD_ASTORE           = BC_astore,
-
-       ICMD_IF_LEQ           = 59,
-       ICMD_IF_LNE           = 60,
-       ICMD_IF_LLT           = 61,
-       ICMD_IF_LGE           = 62,
-       ICMD_IF_LGT           = 63,
-       ICMD_IF_LLE           = 64,
-
-       ICMD_IF_LCMPEQ        = 65,
-       ICMD_IF_LCMPNE        = 66,
-       ICMD_IF_LCMPLT        = 67,
-       ICMD_IF_LCMPGE        = 68,
-       ICMD_IF_LCMPGT        = 69,
-       ICMD_IF_LCMPLE        = 70,
-
-       /* 71 */
-       /* 72 */
-       /* 73 */
-       /* 74 */
-       /* 75 */
-       /* 76 */
-       /* 77 */
-       /* 78 */
-
-       ICMD_IASTORE          = BC_iastore,
-       ICMD_LASTORE          = BC_lastore,
-       ICMD_FASTORE          = BC_fastore,
-       ICMD_DASTORE          = BC_dastore,
-       ICMD_AASTORE          = BC_aastore,
-       ICMD_BASTORE          = BC_bastore,
-       ICMD_CASTORE          = BC_castore,
-       ICMD_SASTORE          = BC_sastore,
-
-       ICMD_POP              = BC_pop,
-       ICMD_POP2             = BC_pop2,
-       ICMD_DUP              = BC_dup,
-       ICMD_DUP_X1           = BC_dup_x1,
-       ICMD_DUP_X2           = BC_dup_x2,
-       ICMD_DUP2             = BC_dup2,
-       ICMD_DUP2_X1          = BC_dup2_x1,
-       ICMD_DUP2_X2          = BC_dup2_x2,
-       ICMD_SWAP             = BC_swap,
-
-       ICMD_IADD             = BC_iadd,
-       ICMD_LADD             = BC_ladd,
-       ICMD_FADD             = BC_fadd,
-       ICMD_DADD             = BC_dadd,
-
-       ICMD_ISUB             = BC_isub,
-       ICMD_LSUB             = BC_lsub,
-       ICMD_FSUB             = BC_fsub,
-       ICMD_DSUB             = BC_dsub,
-
-       ICMD_IMUL             = BC_imul,
-       ICMD_LMUL             = BC_lmul,
-       ICMD_FMUL             = BC_fmul,
-       ICMD_DMUL             = BC_dmul,
-
-       ICMD_IDIV             = BC_idiv,
-       ICMD_LDIV             = BC_ldiv,
-       ICMD_FDIV             = BC_fdiv,
-       ICMD_DDIV             = BC_ddiv,
-
-       ICMD_IREM             = BC_irem,
-       ICMD_LREM             = BC_lrem,
-       ICMD_FREM             = BC_frem,
-       ICMD_DREM             = BC_drem,
-
-       ICMD_INEG             = BC_ineg,
-       ICMD_LNEG             = BC_lneg,
-       ICMD_FNEG             = BC_fneg,
-       ICMD_DNEG             = BC_dneg,
-
-       ICMD_ISHL             = BC_ishl,
-       ICMD_LSHL             = BC_lshl,
-       ICMD_ISHR             = BC_ishr,
-       ICMD_LSHR             = BC_lshr,
-       ICMD_IUSHR            = BC_iushr,
-       ICMD_LUSHR            = BC_lushr,
-
-       ICMD_IAND             = BC_iand,
-       ICMD_LAND             = BC_land,
-       ICMD_IOR              = BC_ior,
-       ICMD_LOR              = BC_lor,
-       ICMD_IXOR             = BC_ixor,
-       ICMD_LXOR             = BC_lxor,
-
-       ICMD_IINC             = BC_iinc,
-
-       ICMD_I2L              = BC_i2l,
-       ICMD_I2F              = BC_i2f,
-       ICMD_I2D              = BC_i2d,
-       ICMD_L2I              = BC_l2i,
-       ICMD_L2F              = BC_l2f,
-       ICMD_L2D              = BC_l2d,
-       ICMD_F2I              = BC_f2i,
-       ICMD_F2L              = BC_f2l,
-       ICMD_F2D              = BC_f2d,
-       ICMD_D2I              = BC_d2i,
-       ICMD_D2L              = BC_d2l,
-       ICMD_D2F              = BC_d2f,
-
-       ICMD_INT2BYTE         = BC_int2byte,
-       ICMD_INT2CHAR         = BC_int2char,
-       ICMD_INT2SHORT        = BC_int2short,
-
-       ICMD_LCMP             = BC_lcmp,
-       ICMD_FCMPL            = BC_fcmpl,
-       ICMD_FCMPG            = BC_fcmpg,
-       ICMD_DCMPL            = BC_dcmpl,
-       ICMD_DCMPG            = BC_dcmpg,
-
-       ICMD_IFEQ             = BC_ifeq,
-       ICMD_IFNE             = BC_ifne,
-       ICMD_IFLT             = BC_iflt,
-       ICMD_IFGE             = BC_ifge,
-       ICMD_IFGT             = BC_ifgt,
-       ICMD_IFLE             = BC_ifle,
-
-       ICMD_IF_ICMPEQ        = BC_if_icmpeq,
-       ICMD_IF_ICMPNE        = BC_if_icmpne,
-       ICMD_IF_ICMPLT        = BC_if_icmplt,
-       ICMD_IF_ICMPGE        = BC_if_icmpge,
-       ICMD_IF_ICMPGT        = BC_if_icmpgt,
-       ICMD_IF_ICMPLE        = BC_if_icmple,
-       ICMD_IF_ACMPEQ        = BC_if_acmpeq,
-       ICMD_IF_ACMPNE        = BC_if_acmpne,
-
-       ICMD_GOTO             = BC_goto,
-       ICMD_JSR              = BC_jsr,
-       ICMD_RET              = BC_ret,
-
-       ICMD_TABLESWITCH      = BC_tableswitch,
-       ICMD_LOOKUPSWITCH     = BC_lookupswitch,
-
-       ICMD_IRETURN          = BC_ireturn,
-       ICMD_LRETURN          = BC_lreturn,
-       ICMD_FRETURN          = BC_freturn,
-       ICMD_DRETURN          = BC_dreturn,
-       ICMD_ARETURN          = BC_areturn,
-       ICMD_RETURN           = BC_return,
-
-       ICMD_GETSTATIC        = BC_getstatic,
-       ICMD_PUTSTATIC        = BC_putstatic,
-       ICMD_GETFIELD         = BC_getfield,
-       ICMD_PUTFIELD         = BC_putfield,
-
-       ICMD_INVOKEVIRTUAL    = BC_invokevirtual,
-       ICMD_INVOKESPECIAL    = BC_invokespecial,
-       ICMD_INVOKESTATIC     = BC_invokestatic,
-       ICMD_INVOKEINTERFACE  = BC_invokeinterface,
-
-       /* 186 */
-
-       ICMD_NEW              = BC_new,
-       ICMD_NEWARRAY         = BC_newarray,
-       ICMD_ANEWARRAY        = BC_anewarray,
-
-       ICMD_ARRAYLENGTH      = BC_arraylength,
-
-       ICMD_ATHROW           = BC_athrow,
-
-       ICMD_CHECKCAST        = BC_checkcast,
-       ICMD_INSTANCEOF       = BC_instanceof,
-
-       ICMD_MONITORENTER     = BC_monitorenter,
-       ICMD_MONITOREXIT      = BC_monitorexit,
-
-       /* 196 */
-
-       ICMD_MULTIANEWARRAY   = BC_multianewarray,
-
-       ICMD_IFNULL           = BC_ifnull,
-       ICMD_IFNONNULL        = BC_ifnonnull,
-
-       /* 200 */
-       /* 201 */
-       /* 202 */
-
-       ICMD_IASTORECONST     = 204,
-       ICMD_LASTORECONST     = 205,
-       ICMD_FASTORECONST     = 206,
-       ICMD_DASTORECONST     = 207,
-       ICMD_AASTORECONST     = 208,
-       ICMD_BASTORECONST     = 209,
-       ICMD_CASTORECONST     = 210,
-       ICMD_SASTORECONST     = 211,
-
-       ICMD_PUTSTATICCONST   = 212,
-       ICMD_PUTFIELDCONST    = 213,
-
-       ICMD_IMULPOW2         = 214,
-       ICMD_LMULPOW2         = 215,
-
-       ICMD_GETEXCEPTION     = 249,
-       ICMD_PHI              = 250,
-
-       ICMD_INLINE_START     = 251,        /* instruction before inlined method  */
-       ICMD_INLINE_END       = 252,        /* instruction after inlined method   */
-       ICMD_INLINE_BODY      = 253,        /* start of inlined body              */
-
-       ICMD_BUILTIN          = 255         /* internal opcode                    */
-};
-
-/* Additional instruction accessors */
-
-methoddesc *instruction_call_site(const instruction *iptr);
-
-static inline bool instruction_has_dst(const instruction *iptr) {
-       if (
-               (icmd_table[iptr->opc].dataflow == DF_INVOKE) ||
-               (icmd_table[iptr->opc].dataflow == DF_BUILTIN)
-               ) {
-               return instruction_call_site(iptr)->returntype.type != TYPE_VOID;
-       } else {
-               return icmd_table[iptr->opc].dataflow >= DF_DST_BASE;
-       }
-}
-
-/***************************** register types *********************************/
-
-#define REG_RES   0         /* reserved register for OS or code generator     */
-#define REG_RET   1         /* return value register                          */
-#define REG_EXC   2         /* exception value register                       */
-#define REG_SAV   3         /* (callee) saved register                        */
-#define REG_TMP   4         /* scratch temporary register (caller saved)      */
-#define REG_ARG   5         /* argument register (caller saved)               */
-
-#define REG_END   -1        /* last entry in tables                           */
-#define PARAMMODE_NUMBERED  0 
-#define PARAMMODE_STUFFED   1
-
-
-/* function prototypes ********************************************************/
-
-/* compiler initialisation */
-void jit_init(void);
-
-/* compiler finalisation */
-void jit_close(void);
-
-/* create a new jitdata */
-jitdata *jit_jitdata_new(methodinfo *m);
-
-/* compile a method with jit compiler */
-u1 *jit_compile(methodinfo *m);
-u1 *jit_recompile(methodinfo *m);
-
-void jit_invalidate_code(methodinfo *m);
-codeinfo *jit_get_current_code(methodinfo *m);
-void jit_request_optimization(methodinfo *m);
-
-/* patch the method entrypoint */
-#if !defined(JIT_COMPILER_VIA_SIGNAL)
-u1 *jit_asm_compile(methodinfo *m, u1 *mptr, u1 *sp, u1 *ra);
-#endif
-void *jit_compile_handle(methodinfo *m, void *pv, void *ra, void *mptr);
-
-s4 jit_complement_condition(s4 opcode);
-
-void jit_renumber_basicblocks(jitdata *jd);
-#if !defined(NDEBUG)
-void jit_check_basicblock_numbers(jitdata *jd);
-#endif
-
-
-/* machine dependent functions ************************************************/
-
-#if defined(ENABLE_JIT)
-void md_init(void);
-#endif
-
-#if defined(ENABLE_INTRP)
-void intrp_md_init(void);
-#endif
-
-void *md_jit_method_patch_address(void *pv, void *ra, void *mptr);
-
-#endif /* _JIT_H */
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
diff --git a/src/vm/jit/jit.hpp b/src/vm/jit/jit.hpp
new file mode 100644 (file)
index 0000000..bb28fce
--- /dev/null
@@ -0,0 +1,495 @@
+/* src/vm/jit/jit.hpp - Just-In-Time compiler
+
+   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_HPP
+#define _JIT_HPP
+
+/* forward typedefs ***********************************************************/
+
+typedef struct jitdata jitdata;
+typedef struct basicblock basicblock;
+typedef struct exception_entry exception_entry;
+
+
+#include "config.h"
+#include "vm/types.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.hpp"
+#include "vm/jit/reg.h"
+#include "vm/jit/replace.hpp"
+#include "vm/jit/stack.h"
+#include "vm/jit/stacktrace.hpp"
+
+#if defined(ENABLE_INLINING)
+# include "vm/jit/inline/inline.h"
+#endif
+
+#include "vm/jit/ir/bytecode.h"
+#include "vm/jit/ir/instruction.hpp"
+
+#if defined(ENABLE_LOOP)
+# include "vm/jit/loop/loop.h"
+#endif
+#if defined(ENABLE_SSA) 
+# include "vm/jit/optimizing/lsra.h"
+#endif
+#if defined(ENABLE_LSRA)
+# include "vm/jit/allocator/lsra.h"
+#endif
+
+#include "vm/jit/verify/typeinfo.h"
+
+
+/* common jit/codegen macros **************************************************/
+
+#if defined(ENABLE_STATISTICS)
+# define COUNT(x)        (x)++
+# define COUNT_SPILLS             /* use COUNT_(READ|WRITE)_SPILLS instead */
+# define COUNT_READ_SPILLS(var) \
+       switch(var->type) { \
+       case TYPE_FLT: count_spills_read_flt++; break; \
+       case TYPE_DBL: count_spills_read_dbl++; break; \
+       default: count_spills_read_ila++; break; \
+       }
+
+# define COUNT_WRITE_SPILLS(var) \
+       switch(var->type) { \
+       case TYPE_FLT: count_spills_write_flt++; break; \
+       case TYPE_DBL: count_spills_write_dbl++; break; \
+       default: count_spills_write_ila++; break; \
+       }
+
+#else
+# define COUNT(x)                /* nothing */
+# define COUNT_SPILLS            /* nothing */
+# define COUNT_READ_SPILLS(x)    /* nothing */
+# define COUNT_WRITE_SPILLS(x)   /* nothing */
+#endif
+
+typedef struct interface_info interface_info;
+
+struct interface_info {
+       s4 flags;
+       s4 regoff;
+};
+
+
+/* jitdata ********************************************************************/
+
+struct jitdata {
+       methodinfo      *m;               /* methodinfo of the method compiled    */
+       codeinfo        *code;
+       codegendata     *cd;
+       registerdata    *rd;
+#if defined(ENABLE_LOOP)
+       loopdata        *ld;
+#endif
+#if defined(ENABLE_SSA) || defined(ENABLE_LSRA)
+       lsradata        *ls;
+#endif
+
+       u4               flags;           /* contains JIT compiler flags          */
+
+       instruction     *instructions;    /* ICMDs, valid between parse and stack */
+       basicblock      *basicblocks;     /* start of basic block list            */
+       stackelement_t  *stack;           /* XXX should become stack.c internal   */
+       s4               instructioncount;/* XXX remove this?                     */
+       s4               basicblockcount; /* number of basic blocks               */
+       s4               stackcount;      /* number of stackelements to allocate  */
+                                      /* (passed from parse to stack)         */
+
+       varinfo         *var;             /* array of variables                   */
+       s4               vartop;          /* next free index in var array         */
+
+       s4               varcount;        /* number of variables in var array     */
+       s4               localcount;      /* number of locals at start of var ar. */
+    s4              *local_map;       /* map for renaming (de-coallescing)    */
+                                        /* locals and keeping the coalescing info for simplereg. */
+                        /* local_map[javaindex * 5 + type] =                     */
+                        /*     >= 0......index into jd->var, or                  */
+                                        /*     UNUSED....this (javaindex,type) pair is not used  */
+
+       s4              *reverselocalmap; /* map from CACAO varindex to javaindex */
+                                         /* (varindex must be < localcount)      */
+
+       s4               maxlocals;       /* max. number of javalocals            */
+
+       interface_info  *interface_map;   /* interface variables (for simplereg)  */
+       s4               maxinterfaces;   /* max. number of interface variables   */
+
+       s4               exceptiontablelength; /* exceptiontable length           */
+       exception_entry *exceptiontable;       /* the exceptiontable              */
+
+       basicblock      *returnblock;          /* block containing the *RETURN    */
+                                              /* (only use if returncount==1)    */
+       s4               returncount;          /* number of return instructions   */
+       bool             branchtoentry;        /* true if first block is a target */
+       bool             branchtoend;          /* true if end dummy is a target   */
+};
+
+#define FOR_EACH_BASICBLOCK(jd, it) \
+       for ((it) = (jd)->basicblocks; (it) != NULL; (it) = (it)->next)
+
+#define UNUSED                     -1
+
+#define JITDATA_FLAG_PARSE               0x00000001
+#define JITDATA_FLAG_VERIFY              0x00000002
+
+#define JITDATA_FLAG_INSTRUMENT          0x00000004
+
+#define JITDATA_FLAG_IFCONV              0x00000008
+#define JITDATA_FLAG_REORDER             0x00000010
+#define JITDATA_FLAG_INLINE              0x00000020
+
+#define JITDATA_FLAG_COUNTDOWN           0x00000100
+
+#define JITDATA_FLAG_SHOWINTERMEDIATE    0x20000000
+#define JITDATA_FLAG_SHOWDISASSEMBLE     0x40000000
+#define JITDATA_FLAG_VERBOSECALL         0x80000000
+
+
+#define JITDATA_HAS_FLAG_PARSE(jd) \
+    ((jd)->flags & JITDATA_FLAG_PARSE)
+
+#define JITDATA_HAS_FLAG_VERIFY(jd) \
+    ((jd)->flags & JITDATA_FLAG_VERIFY)
+
+#define JITDATA_HAS_FLAG_INSTRUMENT(jd) \
+    ((jd)->flags & JITDATA_FLAG_INSTRUMENT)
+
+#define JITDATA_HAS_FLAG_IFCONV(jd) \
+    ((jd)->flags & JITDATA_FLAG_IFCONV)
+
+#define JITDATA_HAS_FLAG_REORDER(jd) \
+    ((jd)->flags & JITDATA_FLAG_REORDER)
+
+#define JITDATA_HAS_FLAG_INLINE(jd) \
+    ((jd)->flags & JITDATA_FLAG_INLINE)
+
+#define JITDATA_HAS_FLAG_COUNTDOWN(jd) \
+    ((jd)->flags & JITDATA_FLAG_COUNTDOWN)
+
+#define JITDATA_HAS_FLAG_SHOWINTERMEDIATE(jd) \
+    ((jd)->flags & JITDATA_FLAG_SHOWINTERMEDIATE)
+
+#define JITDATA_HAS_FLAG_SHOWDISASSEMBLE(jd) \
+    ((jd)->flags & JITDATA_FLAG_SHOWDISASSEMBLE)
+
+#define JITDATA_HAS_FLAG_VERBOSECALL(jd) \
+    ((jd)->flags & JITDATA_FLAG_VERBOSECALL)
+
+
+/* exception_entry ************************************************************/
+
+struct exception_entry {
+       basicblock           *start;
+       basicblock           *end;
+       basicblock           *handler;
+       classref_or_classinfo catchtype; /* catchtype of exc. (NULL == catchall)  */
+       exception_entry      *next;      /* next in list of exceptions when       */
+                                                                        /* loops are copied                      */
+       exception_entry      *down;      /* next exception_entry                  */
+};
+
+
+/* macros for accessing variables *********************************************
+   Use VAROP for s1, s2, s3 and dst operands (eg. VAROP(iptr->s1)),
+   use VAR if you have the variable index (eg. VAR(iptr->sx.s23.s2.args[0])).
+
+******************************************************************************/
+
+#define VAROP(v) (jd->var + (v).varindex)
+#define VAR(i)   (jd->var + (i))
+
+static inline bool var_is_local(const jitdata *jd, s4 i) {
+       return (i < jd->localcount);
+}
+
+static inline bool var_is_prealloc(const jitdata *jd, s4 i) {
+       return ((i >= jd->localcount) && (jd->var[i].flags & PREALLOC));
+}
+
+static inline bool var_is_inout(const jitdata *jd, s4 i) {
+       const varinfo *v = jd->var + i;
+       return (
+               (i >= jd->localcount) && (
+                       (!(v->flags & PREALLOC) && (v->flags & INOUT)) ||
+                       /* special case of TYPE_RET, used with JSR */
+                       ((v->flags & PREALLOC) && (v->flags & INOUT) && (v->type == TYPE_RET))
+               )
+       );
+}
+
+static inline bool var_is_temp(const jitdata *jd, s4 i) {
+       const varinfo *v = jd->var + i;
+       return ((i >= jd->localcount) && !(v->flags & PREALLOC) && !(v->flags & INOUT));
+}
+
+static inline bool var_is_saved(const jitdata *jd, s4 i) {
+       return (jd->var[i].flags & SAVEDVAR);
+}
+
+
+/* basicblock *****************************************************************/
+
+/* flags */
+
+#define BBDELETED            -2
+#define BBUNDEF              -1
+#define BBREACHED            0
+#define BBFINISHED           1
+
+#define BBTYPECHECK_UNDEF    2
+#define BBTYPECHECK_REACHED  3
+
+#define BBTYPE_STD           0  /* standard basic block type                  */
+#define BBTYPE_EXH           1  /* exception handler basic block type         */
+#define BBTYPE_SBR           2  /* subroutine basic block type                */
+
+#define BBFLAG_REPLACEMENT   0x01  /* put a replacement point at the start    */
+
+/* XXX basicblock wastes quite a lot of memory by having four flag fields     */
+/* (flags, bitflags, type and lflags). Probably the last three could be       */
+/* combined without loss of efficiency. The first one could be combined with  */
+/* the others by using bitfields.                                             */
+
+/* XXX "flags" should probably be called "state", as it is an integer state   */
+
+struct basicblock {
+       s4            nr;           /* basic block number                         */
+       s4            flags;        /* used during stack analysis, init with -1   */
+       s4            bitflags;     /* OR of BBFLAG_... constants, init with 0    */
+       s4            type;         /* basic block type (std, xhandler, subroutine*/
+       s4            lflags;       /* used during loop copying, init with 0      */
+
+       s4            icount;       /* number of intermediate code instructions   */
+       instruction  *iinstr;       /* pointer to intermediate code instructions  */
+
+       varinfo      *inlocals;     /* copy of locals on block entry              */
+       s4           *javalocals;   /* map from java locals to cacao variables[+] */
+       s4           *invars;       /* array of in-variables at begin of block    */
+       s4           *outvars;      /* array of out-variables at end of block     */
+       s4            indepth;      /* stack depth at begin of basic block        */
+       s4            outdepth;     /* stack depth end of basic block             */
+       s4            varstart;     /* index of first non-invar block variable    */
+       s4            varcount;     /* number of non-invar block variables        */
+
+       s4            predecessorcount;
+       s4            successorcount;
+       basicblock  **predecessors; /* array of predecessor basic blocks          */
+       basicblock  **successors;   /* array of successor basic blocks            */
+
+       branchref    *branchrefs;   /* list of branches to be patched             */
+
+       basicblock   *next;         /* used to build a BB list (instead of array) */
+       basicblock   *copied_to;    /* points to the copy of this basic block     */
+                                /* when loop nodes are copied                 */
+       basicblock   *original;     /* block of which this block is a clone       */
+                                   /* NULL for the original block itself         */
+       methodinfo   *method;       /* method this block belongs to               */
+       insinfo_inline *inlineinfo; /* inlineinfo for the start of this block     */
+
+       s4            mpc;          /* machine code pc at start of block          */
+
+       /* TODO: those fields are probably usefull for other passes as well. */
+
+#if defined(ENABLE_SSA)         
+       basicblock   *idom;         /* Immediate dominator, parent in dominator tree */
+       basicblock  **domsuccessors;/* Children in dominator tree                 */
+       s4            domsuccessorcount;
+
+       basicblock  **domfrontier;  /* Dominance frontier                         */
+       s4            domfrontiercount;
+
+       basicblock  **exhandlers;   /* Exception handlers for this block */
+       s4            exhandlercount;
+       basicblock  **expredecessors; /* Blocks this block is exception handler for */
+       s4            expredecessorcount;
+       s4            exouts;       /* Number of exceptional exits */
+
+       instruction  *phis;         /* Phi functions */
+       s4            phicount;     /* Number of phi functions */
+
+       void         *vp;           /* Freely used by different passes            */
+#endif
+};
+
+#define FOR_EACH_SUCCESSOR(bptr, it) \
+       for ((it) = (bptr)->successors; (it) != (bptr)->successors + (bptr)->successorcount; ++(it))
+
+#define FOR_EACH_PREDECESSOR(bptr, it) \
+       for ( \
+               (it) = (bptr)->predecessors; \
+               (it) != (bptr)->predecessors + ((bptr)->predecessorcount < 0 ? 0 : (bptr)->predecessorcount); \
+               ++(it) \
+       )
+
+#define FOR_EACH_INSTRUCTION(bptr, it) \
+       for ((it) = (bptr)->iinstr; (it) != (bptr)->iinstr + (bptr)->icount; ++(it))
+
+#define FOR_EACH_INSTRUCTION_REV(bptr, it) \
+       for ((it) = (bptr)->iinstr + (bptr)->icount - 1; (it) != (bptr)->iinstr - 1; --(it))
+
+#if defined(ENABLE_SSA)
+
+#define FOR_EACH_EXHANDLER(bptr, it) \
+       for ((it) = (bptr)->exhandlers; (it) != (bptr)->exhandlers + (bptr)->exhandlercount; ++(it))
+
+#define FOR_EACH_EXPREDECESSOR(bptr, it) \
+       for ((it) = (bptr)->expredecessors; (it) != (bptr)->expredecessors + (bptr)->expredecessorcount; ++(it))
+
+#endif
+
+/* [+]...the javalocals array: This array is indexed by the javaindex (the    */
+/*       local variable index ocurring in the original bytecode). An element  */
+/*       javalocals[javaindex] encodes where to find the contents of the      */
+/*       original variable at this point in the program.                      */
+/*       There are three cases for javalocals[javaindex]:                     */
+/*           >= 0.......it's an index into the jd->var array, where the       */
+/*                      CACAO variable corresponding to the original local    */
+/*                      can be found.                                         */
+/*           UNUSED.....the original variable is not live at this point       */
+/*           < UNUSED...the original variable contains a returnAddress at     */
+/*                      this point. The number of the block to return to can  */
+/*                      be calculated using RETADDR_FROM_JAVALOCAL:           */
+/*                                                                            */
+/*                      javalocals[javaindex] == JAVALOCAL_FROM_RETADDR(nr)   */
+/*                      RETADDR_FROM_JAVALOCAL(javalocals[javaindex]) == nr   */
+
+#define JAVALOCAL_FROM_RETADDR(nr)  (UNUSED - (1 + (nr)))
+#define RETADDR_FROM_JAVALOCAL(jl)  (UNUSED - (1 + (jl)))
+
+
+/* Macro for initializing newly allocated basic block's. It does not
+   need to zero fields, as we zero out the whole basic block array. */
+
+#define BASICBLOCK_INIT(bptr,m)                        \
+       do {                                               \
+               bptr->mpc    = -1;                             \
+               bptr->flags  = -1;                             \
+               bptr->type   = BBTYPE_STD;                     \
+               bptr->method = (m);                            \
+       } while (0)
+
+static inline bool basicblock_reached(const basicblock *bptr) {
+       return (bptr->flags >= BBREACHED);
+}
+
+
+
+/***************************** register types *********************************/
+
+#define REG_RES   0         /* reserved register for OS or code generator     */
+#define REG_RET   1         /* return value register                          */
+#define REG_EXC   2         /* exception value register                       */
+#define REG_SAV   3         /* (callee) saved register                        */
+#define REG_TMP   4         /* scratch temporary register (caller saved)      */
+#define REG_ARG   5         /* argument register (caller saved)               */
+
+#define REG_END   -1        /* last entry in tables                           */
+#define PARAMMODE_NUMBERED  0 
+#define PARAMMODE_STUFFED   1
+
+
+/* function prototypes ********************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* compiler initialisation */
+void jit_init(void);
+
+/* compiler finalisation */
+void jit_close(void);
+
+/* create a new jitdata */
+jitdata *jit_jitdata_new(methodinfo *m);
+
+/* compile a method with jit compiler */
+u1 *jit_compile(methodinfo *m);
+u1 *jit_recompile(methodinfo *m);
+
+void jit_invalidate_code(methodinfo *m);
+codeinfo *jit_get_current_code(methodinfo *m);
+void jit_request_optimization(methodinfo *m);
+
+/* patch the method entrypoint */
+#if !defined(JIT_COMPILER_VIA_SIGNAL)
+void *jit_asm_compile(methodinfo *m, void* mptr, void* sp, void* ra);
+#endif
+void *jit_compile_handle(methodinfo *m, void *pv, void *ra, void *mptr);
+
+s4 jit_complement_condition(s4 opcode);
+
+void jit_renumber_basicblocks(jitdata *jd);
+#if !defined(NDEBUG)
+void jit_check_basicblock_numbers(jitdata *jd);
+#endif
+
+
+/* machine dependent functions ************************************************/
+
+#if defined(ENABLE_JIT)
+void md_init(void);
+#endif
+
+#if defined(ENABLE_INTRP)
+void intrp_md_init(void);
+#endif
+
+void *md_jit_method_patch_address(void *pv, void *ra, void *mptr);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _JIT_HPP
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
index baf6634b4a49308690141da5b1eeae8b5d0f4e07..2cd93a282e8d701f7dbd554a4331cd481c0f62f0 100644 (file)
 
 #if defined(ENABLE_JITCACHE)
 
-/* for mkdir() */
+#include "threads/thread.hpp"
+
+#include "toolbox/list.hpp"
+
+#include "vm/field.hpp"
+
+#include "vm/jit/builtin.hpp"
+#include "vm/jit/code.hpp"
+#include "vm/jit/codegen-common.hpp"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/jitcache.hpp"
+#include "vm/jit/linenumbertable.hpp"
+#include "vm/jit/patcher-common.hpp"
+
+#include "vm/os.hpp"
+#include "vm/string.hpp"
 
 extern "C" {
 
+/* for mkdir() */
 #include <sys/stat.h>
 
 #include <assert.h>
@@ -37,37 +53,25 @@ extern "C" {
 
 #include "md.h"
 
-#include "toolbox/list.h"
 #include "toolbox/logging.h"
 
 #include "mm/memory.h"
 #include "mm/codememory.h"
 
-#include "vm/builtin.h"
 #include "vm/method.h"
 #include "vm/options.h"
 #include "vm/resolve.h"
 #include "vm/types.h"
 
 #include "vm/jit/asmpart.h"
-#include "vm/jit/jit.h"
-#include "vm/jit/code.h"
-#include "vm/jit/patcher-common.h"
-#include "vm/jit/codegen-common.h"
-#include "vm/jit/linenumbertable.h"
 #include "vm/jit/exceptiontable.h"
 #include "vm/jit/methodtree.h"
 
 #include "vm/references.h"
-#include "vm/field.h"
 #include "vm/utf8.h"
 
 }
 
-#include "vm/string.hpp"
-#include "vm/os.hpp"
-#include "vm/jit/jitcache.hpp"
-#include "threads/thread.hpp"
 
 /* TODO: Wrap this in vm/system.h" */
 #include "unistd.h"
@@ -261,7 +265,7 @@ void jitcache_mru_remove(classinfo *c)
 
 void jitcache_list_create(codeinfo *code)
 {
-       code->cachedrefs = list_create(OFFSET(cachedref_t, linkage));
+       code->cachedrefs = new List<cachedref_t>();
 }
 
 
@@ -273,20 +277,7 @@ void jitcache_list_create(codeinfo *code)
 
 void jitcache_list_reset(codeinfo *code)
 {
-       cachedref_t *pr;
-
-       /* free all elements of the list */
-
-       while((pr = (cachedref_t *) list_first(code->cachedrefs)) != NULL) {
-               list_remove(code->cachedrefs, pr);
-
-               FREE(pr, cachedref_t);
-
-#if defined(ENABLE_STATISTICS)
-               if (opt_stat)
-                       size_cachedref -= sizeof(cachedref_t);
-#endif
-       }
+       code->cachedrefs->clear();
 }
 
 
@@ -304,7 +295,8 @@ void jitcache_list_free(codeinfo *code)
 
        /* free the list itself */
 
-       FREE(code->cachedrefs, list_t);
+       delete code->cachedrefs;
+       code->cachedrefs = 0;
 }
 
 
@@ -320,17 +312,14 @@ void jitcache_list_free(codeinfo *code)
 
 static cachedref_t *jitcache_list_find(codeinfo *code, s4 disp)
 {
-       cachedref_t *cr;
-
        /* walk through all cached references for the given codeinfo */
 
-       cr = (cachedref_t *) list_first(code->cachedrefs);
-       while (cr) {
-
-               if (cr->disp == disp)
-                       return cr;
+       for (List<cachedref_t>::iterator it = code->cachedrefs->begin();
+                       it != code->cachedrefs->end(); it++)
+       {
 
-               cr = (cachedref_t *) list_next(code->cachedrefs, cr);
+               if (it->disp == disp)
+                       return &(*it);
        }
 
        return NULL;
@@ -343,48 +332,35 @@ static cachedref_t *jitcache_list_find(codeinfo *code, s4 disp)
 
 *******************************************************************************/
 
-cachedref_t *jitcache_new_cached_ref(cachedreftype type, s4 md_patch, void* ref, s4 disp)
+cachedref_t jitcache_new_cached_ref(cachedreftype type, s4 md_patch, void* ref, s4 disp)
 {
-       cachedref_t *cr;
-
-       /* allocate cachedref on heap (at least freed together with codeinfo) */
-
-       cr = NEW(cachedref_t);
-
-#if defined(ENABLE_STATISTICS)
-       if (opt_stat)
-               size_cachedref += sizeof(cachedref_t);
-#endif
+       cachedref_t cr;
 
        /* set reference information */
 
-       cr->type    = type;
-       cr->md_patch= md_patch;
-       cr->disp    = disp;
-       cr->ref     = ref;
+       cr.type    = type;
+       cr.md_patch= md_patch;
+       cr.disp    = disp;
+       cr.ref     = ref;
 
        return cr;
 }
-/* jitcache_add_cachedref_jd ***************************************************
+/* jitcache_add_cachedref_intern ***********************************************
 
-   Creates a new cached ref appends it to the list in the codeinfo structure
-   *or* attaches it to the *last* patchref_t if it overlaps with the address
-   of the cached reference.
+   Creates a new cached ref appends it to the list in the codeinfo structure.
 
 *******************************************************************************/
 
-void jitcache_add_cached_ref_intern(codeinfo *code, cachedref_t *cachedref)
+void jitcache_add_cached_ref_intern(codeinfo *code, cachedref_t cachedref)
 {
-       cachedref_t *list_cr;
-
-       list_cr = (cachedref_t *) list_first(code->cachedrefs);
+       List<cachedref_t>::iterator it = code->cachedrefs->begin();
 
-       while (list_cr)
+       while (it != code->cachedrefs->end())
        {
-               if (list_cr->disp == cachedref->disp)
+               if (it->disp == cachedref.disp)
                {
-                       assert(list_cr->type == cachedref->type);
-                       assert(list_cr->ref == cachedref->ref);
+                       assert(it->type == cachedref.type);
+                       assert(it->ref == cachedref.ref);
 
                        /* Cachedref for already existing object found. No need to store
                         * it.
@@ -392,10 +368,10 @@ void jitcache_add_cached_ref_intern(codeinfo *code, cachedref_t *cachedref)
                        return;
                }
 
-               list_cr = (cachedref_t *) list_next(code->cachedrefs, list_cr);
+               it++;
        }
 
-       list_add_first(code->cachedrefs, cachedref);
+       code->cachedrefs->push_front(cachedref);
 }
 
 /* jitcache_add_cachedref_jd ***************************************************
@@ -422,10 +398,10 @@ void jitcache_add_cached_ref_jd(jitdata *jd, cachedreftype type, void* ref)
 
 void jitcache_add_cached_ref_md_jd(jitdata *jd, cachedreftype type, s4 md_patch, void* ref)
 {
-       patchref_t       *patchref;
+       patchref_t       patchref;
        codegendata      *cd;
        ptrint                   disp;
-       cachedref_t *cachedref;
+       cachedref_t  cachedref;
 
        if (type >= CRT_OBJECT_HEADER && !ref)
                return;
@@ -435,15 +411,14 @@ void jitcache_add_cached_ref_md_jd(jitdata *jd, cachedreftype type, s4 md_patch,
        disp = (ptrint) (cd->mcodeptr - cd->mcodebase) - SIZEOF_VOID_P;
        cachedref = jitcache_new_cached_ref(type, md_patch, ref, disp);
 
-       patchref = (patchref_t *) list_first(jd->code->patchers);
+       patchref = jd->code->patchers->front();
 
-       if (patchref
-               && (patchref->mpc) <= disp
-               && (patchref->mpc + sizeof(patchref->mcode)) >= disp)
+       if ((patchref.mpc) <= disp
+                 && (patchref.mpc + sizeof(patchref.mcode)) >= disp)
        {
                /* patchers and cachedref overlap: cached ref must
                 * be handled after the patcher.
-         */
+     */
 
                if (opt_DebugJitCache)
                {
@@ -451,12 +426,12 @@ void jitcache_add_cached_ref_md_jd(jitdata *jd, cachedreftype type, s4 md_patch,
                }
 
                /* There can be only one cached ref per patcher currently.
-         * If the need arises to handle more cached refs a list can
-         * be used.
-         */
-               assert(!patchref->attached_ref);
+     * If the need arises to handle more cached refs a list can
+     * be used.
+     */
+               assert(!patchref.attached_ref);
 
-               patchref->attached_ref = cachedref;
+               patchref.attached_ref = &cachedref;
        }
        else
                jitcache_add_cached_ref_intern(jd->code, cachedref);
@@ -471,7 +446,7 @@ void jitcache_add_cached_ref_md_jd(jitdata *jd, cachedreftype type, s4 md_patch,
 
 void jitcache_add_cached_ref(codeinfo *code, cachedreftype type, void* ref, s4 disp)
 {
-       cachedref_t *cr;
+       cachedref_t cr;
 
        /* allocate cachedref on heap (at least freed together with codeinfo) */
        cr = jitcache_new_cached_ref(type, 0, ref,disp);
@@ -494,9 +469,11 @@ void jitcache_handle_cached_ref(cachedref_t *cr, codeinfo *code)
        location = (u1 **) (code->entrypoint + cr->disp);
 
        /* Write the restored reference into the code. */
+#if defined (__ARM__)
        if (cr->md_patch)
                patch_md(cr->md_patch, (ptrint) location, cr->ref);
        else
+#endif
                *location = (u1 *) cr->ref;
 
        md_cacheflush(location, SIZEOF_VOID_P);
@@ -1108,6 +1085,8 @@ int get_cache_file_readable(methodinfo *m)
                if (opt_DebugJitCache)
                        log_message_method("[jitcache] no cache file found for ", m);
 
+               perror("get_cache_file_writable: ");
+
                os::free(dest_file);
 
                return 0;
@@ -1150,6 +1129,8 @@ int get_cache_file_writable(methodinfo *m)
                {
                        if (mkdir_hier(dest_dir, S_IRWXU | S_IRWXG) != 0)
                        {
+                               perror("get_cache_file_writable: ");
+
                                if (opt_DebugJitCache)
                                        log_println("[jitcache] unable to create cache directory: %s", dest_dir);
 
@@ -1167,7 +1148,10 @@ int get_cache_file_writable(methodinfo *m)
                os::free(dest_file);
 
                if (fd <= 0)
+               {
+                       perror("get_cache_file_writable2: ");
                        return 0;
+               }
        }
 
        os::free(dest_file);
@@ -1198,7 +1182,8 @@ int mkdir_hier(char *path, mode_t mode)
                }
        }
 
-       return mkdir(path, mode);
+       if (!mkdir(path, mode) || errno == EEXIST)
+               return 0;
 }
 
 /* get_dest_file ****************************************************************
@@ -1373,36 +1358,36 @@ void store_to_file_patchers(int fd, codeinfo *code)
 {
        int temp = 0;
        void *temp_ptr;
-       patchref_t *pr;
        int j;
 
-       list_t *patchers = code->patchers;
+       int size = code->patchers->size();
 
        /* serialize patchers list */
-       system_write(fd, (const void *) &patchers->size, sizeof(patchers->size));
+       system_write(fd, (const void *) &size, sizeof(size));
        if (opt_DebugJitCache)
-               log_println("store_to_file_patchers - patchers size %d", patchers->size);
+               log_println("store_to_file_patchers - patchers size %d", size);
 
-       for (pr = (patchref_t *) list_first(patchers); pr != NULL; pr = (patchref_t *) list_next(patchers, pr))
+       for (List<patchref_t>::iterator it = code->patchers->begin();
+                       it != code->patchers->end(); it++)
        {
-               temp_ptr = to_offset(code->mcode, (u1 *) pr->mpc);
+               temp_ptr = to_offset(code->mcode, (u1 *) it->mpc);
                system_write(fd, (const void *) &temp_ptr, sizeof(temp_ptr));
 
-               temp_ptr = to_offset(code->mcode, (u1 *) pr->datap);
+               temp_ptr = to_offset(code->mcode, (u1 *) it->datap);
                system_write(fd, (const void *) &temp_ptr, sizeof(temp_ptr));
 
-               system_write(fd, (const void *) &pr->disp, sizeof(pr->disp));
+               system_write(fd, (const void *) &it->disp, sizeof(it->disp));
 
                temp = -1;
                j = 0;
                while (patcher_functions[j].patcher)
                {
-                       if (patcher_functions[j].patcher == pr->patcher)
+                       if (patcher_functions[j].patcher == it->patcher)
                        {
                                temp = j;
                                system_write(fd, (const void *) &j, sizeof(j));
 
-                               (*patcher_functions[j].serializer)(fd, pr, code->m);
+                               (*patcher_functions[j].serializer)(fd, &(*it), code->m);
 
                                if (patcher_functions[j].serializer == s_dummy)
                                        log_println("store_to_file_patchers: unhandled patcher function for %d", j);
@@ -1417,20 +1402,23 @@ void store_to_file_patchers(int fd, codeinfo *code)
                        system_write(fd, (const void *) &temp, sizeof(temp));
                }
 
-               system_write(fd, (const void *) &pr->attached_ref, sizeof(pr->attached_ref));
+               if (it->attached_ref)
+                       temp = 1;
+               
+               system_write(fd, (const void *) &temp, sizeof(temp));
 
-               if (pr->attached_ref)
+               if (it->attached_ref)
                {
-                       store_cachedref(fd, pr->attached_ref);
+                       store_cachedref(fd, it->attached_ref);
 
                        /* Release the cached reference now because it should not be used
                         * in the current Cacao process.
                         */
-                       FREE(pr->attached_ref, cachedref_t);
-                       pr->attached_ref = NULL;
+                       FREE(it->attached_ref, cachedref_t);
+                       it->attached_ref = NULL;
                }
 
-               system_write(fd, (const void *) &pr->mcode, sizeof(pr->mcode));
+               system_write(fd, (const void *) &it->mcode, sizeof(it->mcode));
        }
 }
 
@@ -1442,19 +1430,16 @@ void store_to_file_patchers(int fd, codeinfo *code)
 *******************************************************************************/
 void store_to_file_cachedrefs(int fd, codeinfo *code)
 {
-       cachedref_t *cr;
-
-       list_t *cachedrefs = code->cachedrefs;
+       int size = code->cachedrefs->size();
        if (opt_DebugJitCache)
-               log_println("store_to_file_cachedrefs - cachedrefs size %d", cachedrefs->size);
+               log_println("store_to_file_cachedrefs - cachedrefs size %d", size);
 
        /* serialize cachedrefs list */
-       system_write(fd, (const void *) &cachedrefs->size, sizeof(cachedrefs->size));
+       system_write(fd, (const void *) &size, sizeof(size));
 
-       for (cr = (cachedref_t *) list_first(cachedrefs);
-                cr != NULL;
-                cr = (cachedref_t *) list_next(cachedrefs, cr))
-               store_cachedref(fd, cr);
+       for (List<cachedref_t>::iterator it = code->cachedrefs->begin();
+                       it != code->cachedrefs->end(); it++)
+               store_cachedref(fd, &(*it));
 }
 
 /* store_cachedref *************************************************************
@@ -1576,15 +1561,10 @@ void store_to_file_exceptiontable(int fd, codeinfo *code)
 void store_to_file_linenumbertable(int fd, codeinfo *code)
 {
        void *temp_ptr;
-       linenumbertable_entry_t *lte;
        int count = 0;
-       int i;
-       linenumbertable_t *linenumbertable;
-
-       linenumbertable = code->linenumbertable;
 
        if (code->linenumbertable)
-               count = code->linenumbertable->length;
+               count = code->linenumbertable->_linenumbers.size();
 
        /* serialize patchers list */
        system_write(fd, (const void *) &count, sizeof(count));
@@ -1594,15 +1574,14 @@ void store_to_file_linenumbertable(int fd, codeinfo *code)
 
        if (count)
        {
-               lte = linenumbertable->entries;
-               for (i = 0; i < count; i++)
+               for (std::vector<Linenumber>::iterator it = code->linenumbertable->_linenumbers.begin();
+                       it != code->linenumbertable->_linenumbers.end(); it++)
                {
-                       system_write(fd, (const void *) &lte->linenumber, sizeof(lte->linenumber));
+                       int temp = it->get_linenumber();
+                       system_write(fd, (const void *) &temp, sizeof(temp));
        
-                       temp_ptr = to_offset(code->entrypoint, lte->pc);
+                       temp_ptr = to_offset(code->entrypoint, it->get_pc());
                        system_write(fd, (const void *) &temp_ptr, sizeof(temp_ptr));
-
-                       lte++;
                }
        }
 
@@ -1632,15 +1611,15 @@ void load_from_file_patchers(codeinfo *code, int fd)
 
        for (i = 0;i < count; i++)
        {
-               patchref_t *pr = NEW(patchref_t);
+               patchref_t pr;
 
                system_read(fd, (void *) &temp_ptr, sizeof(temp_ptr));
-               pr->mpc = (ptrint) to_abs(code->mcode, temp_ptr);
+               pr.mpc = (ptrint) to_abs(code->mcode, temp_ptr);
 
                system_read(fd, (void *) &temp_ptr, sizeof(temp_ptr));
-               pr->datap = (ptrint) to_abs(code->mcode, temp_ptr);
+               pr.datap = (ptrint) to_abs(code->mcode, temp_ptr);
 
-               system_read(fd, (void *) &pr->disp, sizeof(pr->disp));
+               system_read(fd, (void *) &pr.disp, sizeof(pr.disp));
 
                system_read(fd, (void *) &temp, sizeof(temp));
                if (temp == -1)
@@ -1648,25 +1627,25 @@ void load_from_file_patchers(codeinfo *code, int fd)
                        vm_abort("Invalid patcher function index loaded!");
                        temp = 0;
                }
-               pr->patcher = patcher_functions[temp].patcher;
+               pr.patcher = patcher_functions[temp].patcher;
 
-               (*patcher_functions[temp].deserializer)(pr, fd, code->m);
+               (*patcher_functions[temp].deserializer)(&pr, fd, code->m);
 
                /* Load the pointer value to decide whether a cached reference must
          * be loaded or not. */
-               system_read(fd, (void *) &pr->attached_ref, sizeof(pr->attached_ref));
+               system_read(fd, (void *) &temp, sizeof(temp));
 
-               if (pr->attached_ref)
+               if (temp)
                {
-                       pr->attached_ref = NULL;
-                       load_cachedref(&pr->attached_ref, fd, code);
+                       pr.attached_ref = 0;
+                       load_cachedref(&pr.attached_ref, fd, code);
                }
 
-               system_read(fd, (void *) &pr->mcode, sizeof(pr->mcode));
+               system_read(fd, (void *) &pr.mcode, sizeof(pr.mcode));
 
-               pr->done = false;
+               pr.done = false;
 
-               list_add_first(code->patchers, pr);
+               code->patchers->push_front(pr);
        }
 }
 
@@ -1702,9 +1681,11 @@ void load_from_file_cachedrefs(codeinfo *code, int fd)
                load_cachedref(&cr, fd, code);
 
                /* Write the restored reference into the code. */
+#if defined (__ARM__)
                if (cr->md_patch)
                        patch_md(cr->md_patch, ((ptrint) code->entrypoint) + cr->disp, cr->ref);
                else
+#endif
                {
                  *((u1 **) (code->entrypoint + cr->disp)) = (u1 *) cr->ref;
                }
@@ -1935,28 +1916,26 @@ void load_from_file_exceptiontable(codeinfo *code, int fd)
 *******************************************************************************/
 void load_from_file_linenumbertable(codeinfo *code, int fd)
 {
-       linenumbertable_entry_t *lte;
        void *temp_ptr;
        int i;
 
-       code->linenumbertable = NEW(linenumbertable_t);
+       code->linenumbertable = new LinenumberTable();
 
-       system_read(fd, (void *) &code->linenumbertable->length, sizeof(code->linenumbertable->length));
+       int size;
+       system_read(fd, (void *) &size, sizeof(size));
 
        if (opt_DebugJitCache)
-               log_println("load_linenumbertable - linenumbertable size %d", code->linenumbertable->length);
-
-       lte = MNEW(linenumbertable_entry_t, code->linenumbertable->length);
-       code->linenumbertable->entries = lte;
+               log_println("load_linenumbertable - linenumbertable size %d", size);
 
-       for (i = 0;i < code->linenumbertable->length; i++)
+       for (i = 0;i < size; i++)
        {
-               system_read(fd, (void *) &lte->linenumber, sizeof(lte->linenumber));
+               int linenumber;
+               system_read(fd, (void *) &linenumber, sizeof(linenumber));
 
                system_read(fd, (void *) &temp_ptr, sizeof(temp_ptr));
-               lte->pc = to_abs(code->entrypoint, temp_ptr);
 
-               lte++;
+               code->linenumbertable->_linenumbers.push_back(
+                       Linenumber(linenumber, to_abs(code->entrypoint, temp_ptr)));
        }
 }
 
index 8bb1c58c713d34454d32048799ba20c3515500fe..250b046fc710e5b1e5cb09ce15296cf03283fe28 100644 (file)
@@ -25,6 +25,8 @@
 #ifndef _JITCACHE_H
 #define _JITCACHE_H
 
+#include "vm/jit/patcher-common.hpp"
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -35,8 +37,6 @@ extern "C" {
 
 #include <stdint.h>
 
-#include "vm/jit/patcher-common.h"
-
 #include "vm/class.h"
 #include "vm/method.h"
 
@@ -72,13 +72,12 @@ typedef enum cachedreftype {
 
 *******************************************************************************/
 
-typedef struct cachedref_t {
+struct cachedref_t {
        cachedreftype type;                     /* type of the cached reference */
        s4                        md_patch;             /* machine dependent back patching */
        s4                disp;         /* displacement of ref in the data segment    */
        void*       ref;          /* reference passed                           */
-       listnode_t    linkage;
-} cachedref_t;
+};
 
 /*
 typedef struct mru_entry_t {
@@ -94,11 +93,11 @@ typedef void (*deserializerfptr) (patchref_t *, int, methodinfo *);
 
 /* jitcache_patcher_function_list_t typedef ***********************************/
 
-typedef struct jitcache_patcher_function_list_t {
+struct jitcache_patcher_function_list_t {
        functionptr patcher;
        serializerfptr serializer;
        deserializerfptr deserializer;
-} jitcache_patcher_function_list_t;
+};
 
 /* function prototypes ********************************************************/
 
diff --git a/src/vm/jit/linenumbertable.c b/src/vm/jit/linenumbertable.c
deleted file mode 100644 (file)
index 9568e3a..0000000
+++ /dev/null
@@ -1,340 +0,0 @@
-/* src/vm/jit/linenumbertable.c - linenumber handling stuff
-
-   Copyright (C) 2007
-   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
-
-   This file is part of CACAO.
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2, or (at
-   your option) any later version.
-
-   This program is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-   02110-1301, USA.
-
-*/
-
-
-#include "config.h"
-
-#include <assert.h>
-#include <stdint.h>
-
-#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(__S390__)
-#  define ADDR_MASK(type, x) ((type)((uintptr_t)(x) & 0x7FFFFFFF))
-#else
-#  define ADDR_MASK(type, x) (x)
-#endif
-
-/* linenumbertable_create ******************************************************
-
-   Creates the linenumber table.  We allocate an array and store the
-   linenumber entry in reverse-order, so we can search the correct
-   linenumber more easily.
-
-*******************************************************************************/
-
-void linenumbertable_create(jitdata *jd)
-{
-       codeinfo                     *code;
-       codegendata                  *cd;
-       linenumbertable_t            *lnt;
-       linenumbertable_entry_t      *lnte;
-       list_t                       *l;
-       linenumbertable_list_entry_t *le;
-       uint8_t                      *pv;
-       void                         *pc;
-
-       /* Get required compiler data. */
-
-       code = jd->code;
-       cd   = jd->cd;
-
-       /* Don't allocate a linenumber table if we don't need one. */
-
-       l = cd->linenumbers;
-
-       if (l->size == 0)
-               return;
-
-       /* Allocate the linenumber table and the entries array. */
-
-       lnt  = NEW(linenumbertable_t);
-       lnte = MNEW(linenumbertable_entry_t, l->size);
-
-#if defined(ENABLE_STATISTICS)
-       if (opt_stat) {
-               count_linenumbertable++;
-
-               size_linenumbertable +=
-                       sizeof(linenumbertable_t) +
-                       sizeof(linenumbertable_entry_t) * l->size;
-       }
-#endif
-
-       /* Fill the linenumber table. */
-
-       lnt->length  = l->size;
-       lnt->entries = lnte;
-
-       /* Fill the linenumber table entries in reverse order, so the
-          search can be forward. */
-
-       /* FIXME I only made this change to prevent a problem when moving
-          to C++. This should be changed back when this file has
-          converted to C++. */
-
-       pv = ADDR_MASK(uint8_t *, code->entrypoint);
-
-       for (le = list_first(l); le != NULL; le = list_next(l, le), lnte++) {
-               /* If the entry contains an mcode pointer (normal case),
-                  resolve it (see doc/inlining_stacktrace.txt for
-                  details). */
-
-               if (le->linenumber >= -2)
-                       pc = pv + le->mpc;
-               else
-                       pc = (void *) le->mpc;
-
-               /* Fill the linenumber table entry. */
-
-               lnte->linenumber = le->linenumber;
-               lnte->pc         = pc;
-       }
-
-       /* Store the linenumber table in the codeinfo. */
-
-       code->linenumbertable = lnt;
-}
-
-
-/* linenumbertable_list_entry_add **********************************************
-
-   Add a line number reference.
-
-   IN:
-      cd.............current codegen data
-      linenumber.....number of line that starts with the given mcodeptr
-
-*******************************************************************************/
-
-void linenumbertable_list_entry_add(codegendata *cd, int32_t linenumber)
-{
-       linenumbertable_list_entry_t *le;
-
-       le = DNEW(linenumbertable_list_entry_t);
-
-       le->linenumber = linenumber;
-       le->mpc        = cd->mcodeptr - cd->mcodebase;
-
-       list_add_first(cd->linenumbers, le);
-}
-
-
-/* linenumbertable_list_entry_add_inline_start *********************************
-
-   Add a marker to the line number table indicating the start of an
-   inlined method body. (see doc/inlining_stacktrace.txt)
-
-   IN:
-      cd ..... current codegen data
-      iptr ... the ICMD_INLINE_BODY instruction
-
-*******************************************************************************/
-
-void linenumbertable_list_entry_add_inline_start(codegendata *cd, instruction *iptr)
-{
-       linenumbertable_list_entry_t *le;
-       insinfo_inline               *insinfo;
-       uintptr_t                     mpc;
-
-       le = DNEW(linenumbertable_list_entry_t);
-
-       le->linenumber = (-2); /* marks start of inlined method */
-       le->mpc        = (mpc = cd->mcodeptr - cd->mcodebase);
-
-       list_add_first(cd->linenumbers, le);
-
-       insinfo = iptr->sx.s23.s3.inlineinfo;
-
-       insinfo->startmpc = mpc; /* store for corresponding INLINE_END */
-}
-
-
-/* linenumbertable_list_entry_add_inline_end ***********************************
-
-   Add a marker to the line number table indicating the end of an
-   inlined method body. (see doc/inlining_stacktrace.txt)
-
-   IN:
-      cd ..... current codegen data
-      iptr ... the ICMD_INLINE_END instruction
-
-   Note:
-      iptr->method must point to the inlined callee.
-
-*******************************************************************************/
-
-void linenumbertable_list_entry_add_inline_end(codegendata *cd, instruction *iptr)
-{
-       linenumbertable_list_entry_t *le;
-       insinfo_inline               *insinfo;
-
-       insinfo = iptr->sx.s23.s3.inlineinfo;
-
-       assert(insinfo);
-
-       le = DNEW(linenumbertable_list_entry_t);
-
-       /* special entry containing the methodinfo * */
-       le->linenumber = (-3) - iptr->line;
-       le->mpc        = (uintptr_t) insinfo->method;
-
-       list_add_first(cd->linenumbers, le);
-
-       le = DNEW(linenumbertable_list_entry_t);
-
-       /* end marker with PC of start of body */
-       le->linenumber = (-1);
-       le->mpc        = insinfo->startmpc;
-
-       list_add_first(cd->linenumbers, le);
-}
-
-
-/* linenumbertable_linenumber_for_pc_intern ************************************
-
-   This function search the line number table for the line
-   corresponding to a given pc. The function recurses for inlined
-   methods.
-
-*******************************************************************************/
-
-static s4 linenumbertable_linenumber_for_pc_intern(methodinfo **pm, linenumbertable_entry_t *lnte, int32_t lntsize, void *pc)
-{
-       linenumbertable_entry_t *lntinline;   /* special entry for inlined method */
-
-       pc = ADDR_MASK(void *, pc);
-
-       for (; lntsize > 0; lntsize--, lnte++) {
-               /* Note: In case of inlining this may actually compare the pc
-                  against a methodinfo *, yielding a non-sensical
-                  result. This is no problem, however, as we ignore such
-                  entries in the switch below. This way we optimize for the
-                  common case (ie. a real pc in lntentry->pc). */
-
-               if (pc >= lnte->pc) {
-                       /* did we reach the current line? */
-
-                       if (lnte->linenumber >= 0)
-                               return lnte->linenumber;
-
-                       /* we found a special inline entry (see
-                          doc/inlining_stacktrace.txt for details */
-
-                       switch (lnte->linenumber) {
-                       case -1: 
-                               /* begin of inlined method (ie. INLINE_END
-                                  instruction) */
-
-                               lntinline = --lnte;            /* get entry with methodinfo * */
-                               lnte--;                        /* skip the special entry      */
-                               lntsize -= 2;
-
-                               /* search inside the inlined method */
-
-                               if (linenumbertable_linenumber_for_pc_intern(pm, lnte, lntsize, pc)) {
-                                       /* the inlined method contained the pc */
-
-                                       *pm = (methodinfo *) lntinline->pc;
-
-                                       assert(lntinline->linenumber <= -3);
-
-                                       return (-3) - lntinline->linenumber;
-                               }
-
-                               /* pc was not in inlined method, continue search.
-                                  Entries inside the inlined method will be skipped
-                                  because their lntentry->pc is higher than pc.  */
-                               break;
-
-                       case -2: 
-                               /* end of inlined method */
-
-                               return 0;
-
-                               /* default: is only reached for an -3-line entry after
-                                  a skipped -2 entry. We can safely ignore it and
-                                  continue searching.  */
-                       }
-               }
-       }
-
-       /* PC not found. */
-
-       return 0;
-}
-
-
-/* linenumbertable_linenumber_for_pc *******************************************
-
-   A wrapper for linenumbertable_linenumber_for_pc_intern.
-
-   NOTE: We have a intern version because the function is called
-   recursively for inlined methods.
-
-*******************************************************************************/
-
-int32_t linenumbertable_linenumber_for_pc(methodinfo **pm, codeinfo *code, void *pc)
-{
-       linenumbertable_t *lnt;
-       int32_t            linenumber;
-
-       /* Get line number table. */
-
-       lnt = code->linenumbertable;
-
-       if (lnt == NULL)
-               return 0;
-
-       /* Get the line number. */
-
-       linenumber = linenumbertable_linenumber_for_pc_intern(pm, lnt->entries, lnt->length, pc);
-
-       return linenumber;
-}
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
diff --git a/src/vm/jit/linenumbertable.cpp b/src/vm/jit/linenumbertable.cpp
new file mode 100644 (file)
index 0000000..379f6de
--- /dev/null
@@ -0,0 +1,256 @@
+/* src/vm/jit/linenumbertable.cpp - linenumber handling stuff
+
+   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 <algorithm>
+
+#include "mm/memory.h"
+
+#include "toolbox/list.hpp"
+
+#if defined(ENABLE_STATISTICS)
+# include "vm/options.h"
+# include "vm/statistics.h"
+#endif
+
+#include "vm/jit/code.hpp"
+#include "vm/jit/codegen-common.hpp"
+#include "vm/jit/linenumbertable.hpp"
+
+
+#if defined(__S390__)
+#  define ADDR_MASK(type, x) ((type)((uintptr_t)(x) & 0x7FFFFFFF))
+#else
+#  define ADDR_MASK(type, x) (x)
+#endif
+
+
+/**
+ * Resolve the linenumber.
+ *
+ * If the entry contains an mcode pointer (normal case), resolve it
+ * (see doc/inlining_stacktrace.txt for details).
+ *
+ * @param code Code structure.
+ */
+void Linenumber::resolve(const codeinfo* code)
+{
+       void* pv = ADDR_MASK(void*, code->entrypoint);
+
+       // TODO Use constant.
+       if (_linenumber >= -2)
+               _pc = (void*) ((uintptr_t) pv + (uintptr_t) _pc);
+}
+
+
+/**
+ * Creates a linenumber table.
+ *
+ * We allocate an array and store the linenumber entry in
+ * reverse-order, so we can search the correct linenumber more easily.
+ *
+ * @param jd JIT data.
+ */
+LinenumberTable::LinenumberTable(jitdata* jd) : _linenumbers(jd->cd->linenumbers->begin(), jd->cd->linenumbers->end())
+{
+       // Get required compiler data.
+       codeinfo* code = jd->code;
+
+#if defined(ENABLE_STATISTICS)
+       if (opt_stat) {
+               count_linenumbertable++;
+
+               size_linenumbertable +=
+                       sizeof(LinenumberTable) +
+                       sizeof(Linenumber) * _linenumbers.size();
+       }
+#endif
+
+       // Resolve all linenumbers in the vector.
+       (void) for_each(_linenumbers.begin(), _linenumbers.end(), std::bind2nd(LinenumberResolver(), code));
+}
+
+
+/**
+ * Search the the line number table for the line corresponding to a
+ * given program counter.
+ *
+ * @param pc Program counter.
+ *
+ * @return Line number.
+ */
+int32_t LinenumberTable::find(methodinfo **pm, void* pc)
+{
+       void* maskpc = ADDR_MASK(void*, pc);
+
+       std::vector<Linenumber>::iterator it = find_if(_linenumbers.begin(), _linenumbers.end(), std::bind2nd(comparator(), maskpc));
+
+       // No matching entry found.
+       if (it == _linenumbers.end())
+               return 0;
+
+       Linenumber& ln = *it;
+       int32_t linenumber = ln.get_linenumber();
+
+       // Check for linenumber entry type.
+       if (linenumber < 0) {
+               os::abort("FIX ME!");
+
+#if 0
+               // We found a special inline entry (see
+               // doc/inlining_stacktrace.txt for details).
+               switch (linenumber) {
+               case -1:
+                       // Begin of an inlined method (ie. INLINE_END instruction.
+                       lntinline = --lnte;            /* get entry with methodinfo * */
+                       lnte--;                        /* skip the special entry      */
+
+                       /* search inside the inlined method */
+
+                       if (linenumbertable_linenumber_for_pc_intern(pm, lnte, lntsize, pc)) {
+                               /* the inlined method contained the pc */
+
+                               *pm = (methodinfo *) lntinline->pc;
+
+                               assert(lntinline->linenumber <= -3);
+
+                               return (-3) - lntinline->linenumber;
+                       }
+
+                       /* pc was not in inlined method, continue search.
+                          Entries inside the inlined method will be skipped
+                          because their lntentry->pc is higher than pc.  */
+                       break;
+
+               case -2: 
+                       /* end of inlined method */
+
+                       return 0;
+
+                       /* default: is only reached for an -3-line entry after
+                          a skipped -2 entry. We can safely ignore it and
+                          continue searching.  */
+               }
+#endif
+       }
+
+       // Normal linenumber entry, return it.
+       return linenumber;
+}
+
+
+/* linenumbertable_list_entry_add **********************************************
+
+   Add a line number reference.
+
+   IN:
+      cd.............current codegen data
+      linenumber.....number of line that starts with the given mcodeptr
+
+*******************************************************************************/
+
+void linenumbertable_list_entry_add(codegendata *cd, int32_t linenumber)
+{
+       void* pc = (void*) (cd->mcodeptr - cd->mcodebase);
+       Linenumber ln(linenumber, pc);
+
+       cd->linenumbers->push_front(ln);
+}
+
+
+/* linenumbertable_list_entry_add_inline_start *********************************
+
+   Add a marker to the line number table indicating the start of an
+   inlined method body. (see doc/inlining_stacktrace.txt)
+
+   IN:
+      cd ..... current codegen data
+      iptr ... the ICMD_INLINE_BODY instruction
+
+*******************************************************************************/
+
+void linenumbertable_list_entry_add_inline_start(codegendata *cd, instruction *iptr)
+{
+       void* pc = (void*) (cd->mcodeptr - cd->mcodebase);
+
+       Linenumber ln(-2 /* marks start of inlined method */, pc);
+
+       cd->linenumbers->push_front(ln);
+
+       insinfo_inline* insinfo = iptr->sx.s23.s3.inlineinfo;
+       insinfo->startmpc = (int32_t) (uintptr_t) pc; /* store for corresponding INLINE_END */
+}
+
+
+/* linenumbertable_list_entry_add_inline_end ***********************************
+
+   Add a marker to the line number table indicating the end of an
+   inlined method body. (see doc/inlining_stacktrace.txt)
+
+   IN:
+      cd ..... current codegen data
+      iptr ... the ICMD_INLINE_END instruction
+
+   Note:
+      iptr->method must point to the inlined callee.
+
+*******************************************************************************/
+
+void linenumbertable_list_entry_add_inline_end(codegendata *cd, instruction *iptr)
+{
+       insinfo_inline* insinfo = iptr->sx.s23.s3.inlineinfo;
+
+       // Sanity check.
+       assert(insinfo);
+
+       // Special entry containing the methodinfo.
+       Linenumber ln((-3) - iptr->line, insinfo->method);
+
+       cd->linenumbers->push_front(ln);
+
+       // End marker with PC of start of body.
+       Linenumber lne(-1, (void*) insinfo->startmpc);
+
+       cd->linenumbers->push_front(lne);
+}
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
diff --git a/src/vm/jit/linenumbertable.h b/src/vm/jit/linenumbertable.h
deleted file mode 100644 (file)
index ce915d3..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-/* src/vm/jit/linenumbertable.h - linenumber table
-
-   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 _LINENUMBERTABLE_H
-#define _LINENUMBERTABLE_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* forward typedefs ***********************************************************/
-
-typedef struct linenumbertable_t            linenumbertable_t;
-typedef struct linenumbertable_entry_t      linenumbertable_entry_t;
-typedef struct linenumbertable_list_entry_t linenumbertable_list_entry_t;
-
-
-#include "config.h"
-
-#include <stdint.h>
-
-#include "toolbox/list.h"
-
-#include "vm/method.h"
-
-#include "vm/jit/jit.h"
-#include "vm/jit/code.h"
-#include "vm/jit/codegen-common.h"
-
-
-/* linenumbertable_t **********************************************************/
-
-struct linenumbertable_t {
-       int32_t                  length;    /* length of the entries array        */
-       linenumbertable_entry_t *entries;   /* actual linenumber entries          */
-};
-
-
-/* linenumbertable_entry_t *****************************************************
-
-   NOTE: See doc/inlining_stacktrace.txt for special meanings of line
-   and pc.
-
-*******************************************************************************/
-
-struct linenumbertable_entry_t {
-       int32_t  linenumber;                /* linenumber of this entry           */
-       void    *pc;                        /* PC where this linenumber starts    */
-};
-
-
-/* linenumbertable_list_entry_t ***********************************************/
-
-struct linenumbertable_list_entry_t {
-       int32_t    linenumber;      /* line number, used for inserting into the   */
-                                   /* table and for validity checking            */
-                                   /* -1......start of inlined body              */
-                                   /* -2......end of inlined body                */
-                                   /* <= -3...special entry with methodinfo *    */
-                                                               /* (see doc/inlining_stacktrace.txt)          */
-       ptrint     mpc;             /* machine code program counter of first      */
-                                   /* instruction for given line                 */
-                                   /* NOTE: for linenumber <= -3 this is a the   */
-                                   /* (methodinfo *) of the inlined method       */
-       listnode_t linkage;
-};
-
-
-/* function prototypes ********************************************************/
-
-void    linenumbertable_create(jitdata *jd);
-
-void    linenumbertable_list_entry_add(codegendata *cd, int32_t linenumber);
-void    linenumbertable_list_entry_add_inline_start(codegendata *cd, instruction *iptr);
-void    linenumbertable_list_entry_add_inline_end(codegendata *cd, instruction *iptr);
-
-int32_t linenumbertable_linenumber_for_pc(methodinfo **pm, codeinfo *code, void *pc);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _LINENUMBERTABLE_H */
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
diff --git a/src/vm/jit/linenumbertable.hpp b/src/vm/jit/linenumbertable.hpp
new file mode 100644 (file)
index 0000000..0d6143e
--- /dev/null
@@ -0,0 +1,147 @@
+/* src/vm/jit/linenumbertable.hpp - linenumber table
+
+   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 _LINENUMBERTABLE_HPP
+#define _LINENUMBERTABLE_HPP
+
+#include "config.h"
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+#include <functional>
+#include <vector>
+#endif
+
+#include "toolbox/list.hpp"
+
+#include "vm/method.h"
+
+#include "vm/jit/jit.hpp"
+#include "vm/jit/code.hpp"
+
+#include "vm/jit/ir/instruction.hpp"
+
+
+#ifdef __cplusplus
+
+/**
+ * Represents a Java line number.
+ */
+class Linenumber {
+private:
+       // TODO Add constants.
+       /* -1......start of inlined body              */
+       /* -2......end of inlined body                */
+       /* <= -3...special entry with methodinfo *    */
+       /* (see doc/inlining_stacktrace.txt)          */
+
+       int32_t _linenumber;
+       void*   _pc;
+
+public:
+       Linenumber(int32_t linenumber, void* pc) : _linenumber(linenumber), _pc(pc) {}
+
+       inline int32_t get_linenumber() const { return _linenumber; }
+       inline void*   get_pc        () const { return _pc; }
+
+       void resolve(const codeinfo* code);
+};
+
+
+/**
+ * Unary function to resolve Linenumber objects.
+ */
+class LinenumberResolver : public std::binary_function<Linenumber, codeinfo*, void> {
+public:
+       // Unary resolve function.
+       void operator() (Linenumber& ln, const codeinfo* code) const
+       {
+               ln.resolve(code);
+       }
+};
+
+
+/**
+ * Linenumber table of a Java method.
+ */
+class LinenumberTable {
+public:
+       std::vector<Linenumber> _linenumbers;
+private:
+
+       // Comparator class.
+       class comparator : public std::binary_function<Linenumber, void*, bool> {
+       public:
+               bool operator() (const Linenumber& ln, const void* pc) const
+               {
+                       return (pc >= ln.get_pc());
+               }
+       };
+
+public:
+       LinenumberTable(jitdata* jd);
+       LinenumberTable() { }
+       ~LinenumberTable();
+
+       int32_t find(methodinfo **pm, void* pc);
+};
+
+#else
+
+typedef struct LinenumberTable LinenumberTable;
+
+#endif
+
+#include "vm/jit/codegen-common.hpp"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void    linenumbertable_list_entry_add(codegendata *cd, int32_t linenumber);
+void    linenumbertable_list_entry_add_inline_start(codegendata *cd, instruction *iptr);
+void    linenumbertable_list_entry_add_inline_end(codegendata *cd, instruction *iptr);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _LINENUMBERTABLE_HPP
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
index 43a7dad53c6e7c8558b960f94509082155f61706..211e492bde7e519dbeb908ffbeac72f5714d2c5a 100644 (file)
@@ -35,7 +35,7 @@
 #include "mm/memory.h"
 #include "toolbox/logging.h"
 
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
 #include "vm/jit/stack.h"
 
 #include "vm/jit/loop/analyze.h"
index d8fbc5e0196904fef374d279455e8c6f5169d3f0..5b6650b2460413f140ab9b1e05d655088bee9dc0 100644 (file)
@@ -36,7 +36,7 @@
 
 #include "config.h"
 
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
 
 
 /* function prototypes ********************************************************/
index 09cd21d5384dca04ab91ecc15a5570d94a83763d..91f580d4bdcf3a21cfdbad0d4ac9a610df44bc66 100644 (file)
@@ -38,7 +38,7 @@
 
 #include "mm/memory.h"
 #include "toolbox/logging.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
 #include "vm/jit/loop/graph.h"
 #include "vm/jit/loop/loop.h"
 
index e817f02ba0dc012836bb7d64f915f5bdc9fe4986..56d4ee09ffd0cf9f9b3ac7d722471b09209b49c3 100644 (file)
@@ -43,7 +43,7 @@
 #include "mm/memory.h"
 #include "toolbox/logging.h"
 #include "vm/global.h" 
-#include "vm/jit/jit.h"        
+#include "vm/jit/jit.hpp"      
 #include "vm/jit/loop/loop.h"
 #include "vm/jit/loop/graph.h"
 #include "vm/jit/loop/tracing.h"
index 586c729a3ee04d41f3966e1f4036a4bb12953029..0a2eaa54affa43b9861c776aec7223e1c88ab1b5 100644 (file)
@@ -32,7 +32,7 @@
 #include "vm/global.h"
 #include "vm/method.h"
 
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
 
 
 /*     Different types for struct Trace                                                                                */
index 13df1e949bc33f7854deb4d3e7771a603546fe02..83e273e7dffeab92286ba9403d4263a6b6287d1e 100644 (file)
@@ -35,7 +35,7 @@
 
 
 #include "mm/memory.h"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/resolve.h"
 #include "vm/jit/loop/loop.h"
 #include "vm/jit/loop/tracing.h"
index d506be50e45d59500dcbf01dad8314599b70e2cd..fe4653be221cba35b10f2c2c7ae923c73c0a142f 100644 (file)
@@ -33,7 +33,7 @@
 #ifndef _TRACING_H
 #define _TRACING_H
 
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
 
 
 typedef struct Trace Trace;
index 5799e1a78fe589732647e7916bcb4100b4de6c56..85da92d0836156c14b7e58d42d36fdf182d8f04a 100644 (file)
@@ -51,6 +51,7 @@ libarch_la_SOURCES = \
        emit.c \
        patcher.c \
        \
+       md-stubs.hpp \
        md-trap.h \
        md.c \
        md.h
index 7441e256d7cb04f7b1c2a552f6c904e04e0c62d1..5498aabeebe0dceaa445a0469e51e0491ac73140 100644 (file)
@@ -33,8 +33,6 @@
 
 /* define architecture features ***********************************************/
 
-#define U8_AVAILABLE                     1
-
 #define SUPPORT_DIVISION                 1
 #define SUPPORT_LONG                     1
 
index 22e9ea93e5615366bda3f43feefe0729fb667740..6a0254b8c89e7f218e69e8ae4948f85521475f09 100644 (file)
 #include "vm/jit/m68k/emit.h"
 
 #include "mm/memory.h"
-#include "native/jni.h"
-#include "native/localref.h"
-#include "native/native.h"
 
-#include "threads/lock-common.h"
+#include "native/localref.hpp"
+#include "native/native.hpp"
 
-#include "vm/builtin.h"
+#include "threads/lock.hpp"
+
+#include "vm/jit/builtin.hpp"
 #include "vm/exceptions.hpp"
 #include "vm/global.h"
-#include "vm/loader.h"
+#include "vm/loader.hpp"
 #include "vm/options.h"
 #include "vm/utf8.h"
 #include "vm/vm.hpp"
 
 #include "vm/jit/asmpart.h"
-#include "vm/jit/codegen-common.h"
-#include "vm/jit/patcher-common.h"
+#include "vm/jit/codegen-common.hpp"
+#include "vm/jit/patcher-common.hpp"
 #include "vm/jit/dseg.h"
-#include "vm/jit/linenumbertable.h"
-#include "vm/jit/emit-common.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/linenumbertable.hpp"
+#include "vm/jit/emit-common.hpp"
+#include "vm/jit/jit.hpp"
 #include "vm/jit/abi.h"
 #include "vm/jit/parse.h"
 #include "vm/jit/reg.h"
-#include "vm/jit/replace.h"
+#include "vm/jit/replace.hpp"
 #include "vm/jit/stacktrace.hpp"
 #include "vm/jit/trap.h"
 
index 689dd9b6a64b9ed3873809bcae88796ed0a54ab8..0cb13d0fa215b61b8bb80eb7088e1586b4c96466 100644 (file)
@@ -1,9 +1,7 @@
 /* src/vm/jit/m68k/codegen.h
 
-   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
-   C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
-   E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
-   J. Wenninger, Institut f. Computersprachen - TU Wien
+   Copyright (C) 1996-2005, 2006, 2007, 2008
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
 
 #define PATCHER_NOPS \
        do { M_TPFL; M_TPF; M_TPF } while (0);
 
-#define PATCHER_CALL_SIZE      (3*2)
-
-/* stub defines ***************************************************************/
-
-#define COMPILERSTUB_CODESIZE (2+2)
+#define PATCHER_CALL_SIZE      2
 
 
 /* coldfire instruction format:
index c6002a36b500379f8f6f4617fb5c2b59a1fd0f06..81fc1288f2d5ac61e799535cf29cbfecaccc7ccd 100644 (file)
 
 #include "mm/memory.h"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 
 #include "vm/jit/asmpart.h"
-#include "vm/jit/emit-common.h"
+#include "vm/jit/emit-common.hpp"
 #include "vm/jit/trace.hpp"
 #include "vm/jit/trap.h"
 
index 20fa2ea8e119c5235fcfc445aa62f72caf545643..c0358ea8d3a661d3e33a6d65c9abd9b4acacb8ae 100644 (file)
@@ -31,7 +31,7 @@
 
 #include "vm/types.h"
 #include "vm/vm.hpp"
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/codegen-common.hpp"
 
 void emit_mov_imm_reg (codegendata *cd, s4 imm, s4 dreg);
 void emit_mov_imm_areg(codegendata *cd, s4 imm, s4 dreg);
diff --git a/src/vm/jit/m68k/md-stubs.hpp b/src/vm/jit/m68k/md-stubs.hpp
new file mode 100644 (file)
index 0000000..e7f84f6
--- /dev/null
@@ -0,0 +1,56 @@
+/* src/vm/jit/m68k/md-stubs.hpp - m68k JIT stubs
+
+   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 _MD_STUBS_HPP
+#define _MD_STUBS_HPP
+
+#include "config.h"
+
+
+/**
+ * Return the code size of a compiler on a m68k architecture.
+ *
+ * @return Code size in bytes.
+ */
+int CompilerStub::get_code_size()
+{
+       return 2 + 2;
+}
+
+#endif // _MD_STUBS_HPP
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
index bc64f4c73587868764b66054f8b02db2dbde342b..5514cc4b885b87ba0c3d5111058a262d8010f7d7 100644 (file)
@@ -33,7 +33,7 @@
 #include <assert.h>
 #include <stdint.h>
 
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/codegen-common.hpp"
 #include "vm/jit/methodtree.h"
 
 
index a5e03b50357b9bf29f53481b2ff0641085e39c8b..d3f27b76f9e618e24da75e28248a66c92dbbfe3c 100644 (file)
 #include "vm/jit/m68k/md.h"
 
 #include "mm/memory.h"
-#include "native/native.h"
+#include "native/native.hpp"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/class.h"
-#include "vm/field.h"
+#include "vm/field.hpp"
 #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/patcher-common.hpp"
 
 #include "codegen.h"
 
@@ -130,9 +130,6 @@ bool patcher_invokevirtual(patchref_t *pr)
        /* patch back original code */
        PATCH_BACK_ORIGINAL_MCODE;
 
-       /* if we show NOPs, we have to skip them */
-       if (opt_shownops) ra += PATCHER_CALL_SIZE;
-
        assert( *((u2*)(ra+8)) == 0x286b);
 
        /* patch vftbl index */
@@ -173,9 +170,6 @@ bool patcher_invokestatic_special(patchref_t *pr)
        /* patch back original code */
        PATCH_BACK_ORIGINAL_MCODE;
 
-       /* patch stubroutine */
-       if (opt_shownops) disp += PATCHER_CALL_SIZE;
-
        *((ptrint *) (disp+2)) = (ptrint) m->stubroutine;
 
        /* synchronize inst cache */
@@ -209,7 +203,6 @@ bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
        PATCH_BACK_ORIGINAL_MCODE;
 
        /* patch the classinfo pointer */
-       if (opt_shownops) disp += PATCHER_CALL_SIZE;
        *((ptrint *) (disp+2)) = (ptrint) c;
 
        /* synchronize inst cache */
@@ -248,7 +241,6 @@ bool patcher_get_putstatic(patchref_t *pr)
        md_icacheflush(pr->mpc, 2);
 
        /* patch the field value's address */
-       if (opt_shownops) disp += PATCHER_CALL_SIZE;
        assert(*((uint16_t*)(disp)) == 0x247c);
        *((intptr_t *) (disp+2)) = (intptr_t) fi->value;
 
@@ -283,9 +275,6 @@ bool patcher_get_putfield(patchref_t *pr)
        PATCH_BACK_ORIGINAL_MCODE;
        md_icacheflush(pr->mpc, 2);
 
-       /* if we show NOPs, we have to skip them */
-       if (opt_shownops) ra += PATCHER_CALL_SIZE;
-
        /* patch the field's offset */
        if (IS_LNG_TYPE(fi->type)) {
                /*
@@ -371,7 +360,6 @@ bool patcher_resolve_classref_to_flags(patchref_t *pr)
        md_icacheflush(pr->mpc, 2);
 
        /* patch class flags */
-       if (opt_shownops) disp += PATCHER_CALL_SIZE;
        assert( (*((u2*)(disp)) == 0x263c) || (*((u2*)(disp)) == 0x283c) );
        *((s4 *) (disp + 2)) = (s4) c->flags;
 
@@ -415,7 +403,6 @@ bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
        md_icacheflush(pr->mpc, 2);
 
        /* patch super class' vftbl */
-       if (opt_shownops) disp += PATCHER_CALL_SIZE;
        assert( (*((u2*)disp) == 0x287c) || (*((u2*)disp)== 0x267c) );
 
        *((s4 *) (disp+2)) = (s4) c->vftbl;
@@ -460,9 +447,6 @@ bool patcher_instanceof_interface(patchref_t *pr)
        PATCH_BACK_ORIGINAL_MCODE;
        md_icacheflush(pr->mpc, 2);
 
-       /* if we show NOPs, we have to skip them */
-       if (opt_shownops) ra += PATCHER_CALL_SIZE;
-               
        /* patch super class index */
        disp = -(c->index);
        assert( *((u2*)(ra + 8)) == 0xd8bc );
@@ -514,9 +498,6 @@ bool patcher_checkcast_interface(patchref_t *pr)
        PATCH_BACK_ORIGINAL_MCODE;
        md_icacheflush(pr->mpc, 2);
 
-       /* if we show NOPs, we have to skip them */
-       if (opt_shownops) ra += PATCHER_CALL_SIZE;
-
        /* patch super class index */
        disp = -(c->index);
        assert ( *((u2 *)(ra + 8)) == 0xd8bc );
@@ -559,7 +540,6 @@ bool patcher_resolve_native_function(patchref_t *pr)
        md_icacheflush(pr->mpc, 2);
 
        /* patch native function pointer */
-       if (opt_shownops) disp += PATCHER_CALL_SIZE;
        *((ptrint *) (disp + 2)) = (ptrint) f;
 
        /* synchronize data cache */
@@ -601,7 +581,6 @@ bool patcher_invokeinterface(patchref_t *pr)
        md_icacheflush(pr->mpc, 2);
 
        /* if we show NOPs, we have to skip them */
-       if (opt_shownops) ra += PATCHER_CALL_SIZE;
        assert( *((uint32_t*)ra) == 0x246f0000 );
 
        /* patch interfacetable index (first #0) */
@@ -620,6 +599,8 @@ bool patcher_invokeinterface(patchref_t *pr)
 
        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
index 86ef145db86d6c49e85230466cfab5bfcd2b07bb..751957ff1fe7be62abad0efcd7bea12a2830425f 100644 (file)
@@ -57,6 +57,7 @@ libarch_la_SOURCES = \
        \
        md-abi.c \
        md-abi.h \
+       md-stubs.hpp \
        md-trap.h \
        md.c \
        md.h
index a6c4864d90395ed70f244e5a958ab28c62393c7e..e2ed877694cd5993a90e5f7b22e2e2a6c1a49faf 100644 (file)
@@ -35,8 +35,6 @@
 
 /* define architecture features ***********************************************/
 
-#define U8_AVAILABLE                     1
-
 #if SIZEOF_VOID_P == 8
 
 #define SUPPORT_DIVISION                 1
index eb73de9b99e70b7a36385ec5c781a552158f10f4..5260e939d6b802dbd998156d9f8504b621fe319f 100644 (file)
 
 #include "mm/memory.h"
 
-#include "native/localref.h"
-#include "native/native.h"
+#include "native/localref.hpp"
+#include "native/native.hpp"
 
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/class.h"
 #include "vm/exceptions.hpp"
 #include "vm/options.h"
 
 #include "vm/jit/abi.h"
 #include "vm/jit/asmpart.h"
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/codegen-common.hpp"
 #include "vm/jit/dseg.h"
-#include "vm/jit/emit-common.h"
-#include "vm/jit/jit.h"
-#include "vm/jit/linenumbertable.h"
-#include "vm/jit/patcher-common.h"
+#include "vm/jit/emit-common.hpp"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/linenumbertable.hpp"
+#include "vm/jit/patcher-common.hpp"
 #include "vm/jit/reg.h"
-#include "vm/jit/replace.h"
+#include "vm/jit/replace.hpp"
 #include "vm/jit/trap.h"
 
 #if defined(ENABLE_LSRA)
index c759180bf28316a2f11b141726422f52f07c8cd9..f1819f84887019bfde43a03560182b44a9a74603 100644 (file)
@@ -1,9 +1,7 @@
 /* src/vm/jit/mips/codegen.h - code generation macros and definitions for MIPS
 
-   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
-   C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
-   E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
-   J. Wenninger, Institut f. Computersprachen - TU Wien
+   Copyright (C) 1996-2005, 2006, 2007, 2008
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
 
@@ -31,7 +29,7 @@
 #include "config.h"
 #include "vm/types.h"
 
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
 
 
 /* additional functions and macros to generate code ***************************/
     } while (0)
 
 
-/* stub defines ***************************************************************/
-
-#define COMPILERSTUB_CODESIZE    1 * 4
-
-
 /* macros to create code ******************************************************/
 
 /* code generation macros operands:
 
 /* macros for all used commands (see a MIPS-manual for description) ***********/
 
+#define M_RESERVED              M_RTYPE(0x3b, 0, 0, 0, 0, 0)
+
 /* load/store macros use the form OPERATION(source/dest, base, offset)        */
 
 #define M_LDA(a,b,disp) \
index ef30af384eced91c0d588da6b9c1de8aee28aa83..86fbb11c4bdefed381822b9f901d3c7ba3a485d2 100644 (file)
 
 #include "mm/memory.h"
 
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/options.h"
 
 #include "vm/jit/abi.h"
 #include "vm/jit/abi-asm.h"
 #include "vm/jit/asmpart.h"
 #include "vm/jit/dseg.h"
-#include "vm/jit/emit-common.h"
-#include "vm/jit/jit.h"
-#include "vm/jit/patcher-common.h"
-#include "vm/jit/replace.h"
+#include "vm/jit/emit-common.hpp"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/patcher-common.hpp"
+#include "vm/jit/replace.hpp"
 #include "vm/jit/trap.h"
 
 
@@ -615,14 +615,11 @@ void emit_trap_compiler(codegendata *cd)
 
 uint32_t emit_trap(codegendata *cd)
 {
-       uint32_t mcode;
+       // Get machine code which is patched back in later. The trap is 1
+       // instruction word long.
+       uint32_t mcode = *((uint32_t*) cd->mcodeptr);
 
-       /* Get machine code which is patched back in later. The
-          trap is 1 instruction word long. */
-
-       mcode = *((uint32_t *) cd->mcodeptr);
-
-       M_ALD_INTERN(REG_ZERO, REG_ZERO, TRAP_PATCHER);
+       M_RESERVED;
 
        return mcode;
 }
index 8b54c15e80fce91954669a7666b5aa18baf97f67..39117af25e977df19bae4686bfbf16433def1c09 100644 (file)
@@ -41,7 +41,7 @@
 #include "vm/signallocal.h"
 
 #include "vm/jit/asmpart.h"
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/codegen-common.hpp"
 
 
 /* md_init *********************************************************************
index e94b20d76faa8d962f9b7d5b6f4f726d1e780d6b..f7b6601de5b8556c29b47905d88115ebc1df5156 100644 (file)
@@ -215,28 +215,71 @@ void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
 
                /* fall-through */
 
-       case TRAP_PATCHER:
-               if (p == NULL) {
-                       /* We set the PC again because the cause may have changed
-                          the XPC. */
+       default:
+               _gregs[REG_ITMP1_XPTR] = (uintptr_t) p;
+               _gregs[REG_ITMP2_XPC]  = (uintptr_t) xpc;
+#if defined(__UCLIBC__)
+               _gregs[CTX_EPC]        = (uintptr_t) asm_handle_exception;
+#else
+               _mc->pc                = (uintptr_t) asm_handle_exception;
+#endif
+       }
+}
+
+
+/**
+ * Signal handler for patcher calls.
+ */
+void md_signal_handler_sigill(int sig, siginfo_t* siginfo, void* _p)
+{
+       ucontext_t* _uc = (struct ucontext *) _p;
+       mcontext_t* _mc = &_uc->uc_mcontext;
+       greg_t* _gregs;
 
 #if defined(__UCLIBC__)
-                       _gregs[CTX_EPC] = (uintptr_t) xpc;
+       _gregs = _mc->gpregs;
+#else  
+       _gregs = _mc->gregs;
+#endif
+
+       // In glibc's ucontext.h the registers are defined as long long
+       // int, even for MIPS32, so we cast them.  This is not the case
+       // for uClibc.
+       void* pv  = (void*) (uintptr_t) _gregs[REG_PV];
+       void* sp  = (void*) (uintptr_t) _gregs[REG_SP];
+       void* ra  = (void*) (uintptr_t) _gregs[REG_RA]; // The RA is correct for leaf methods.
+
+#if defined(__UCLIBC__)
+       void* xpc = (void*) (uintptr_t) _gregs[CTX_EPC];
 #else
-                       _mc->pc         = (uintptr_t) xpc;
+       void* xpc = (void*) (uintptr_t) _mc->pc;
 #endif
-                       break;
-               }
 
-               /* fall-through */
-               
-       default:
+       // This signal is always a patcher.
+       int      type = TRAP_PATCHER;
+       intptr_t val  = 0;
+
+       // Handle the trap.
+       void* p = trap_handle(type, val, pv, sp, ra, xpc, _p);
+
+       // Set registers if we have an exception, continue execution
+       // otherwise.
+       if (p != NULL) {
                _gregs[REG_ITMP1_XPTR] = (uintptr_t) p;
                _gregs[REG_ITMP2_XPC]  = (uintptr_t) xpc;
 #if defined(__UCLIBC__)
                _gregs[CTX_EPC]        = (uintptr_t) asm_handle_exception;
 #else
                _mc->pc                = (uintptr_t) asm_handle_exception;
+#endif
+       }
+       else {
+               // We set the PC again because the cause may have changed the
+               // XPC.
+#if defined(__UCLIBC__)
+               _gregs[CTX_EPC] = (uintptr_t) xpc;
+#else
+               _mc->pc         = (uintptr_t) xpc;
 #endif
        }
 }
diff --git a/src/vm/jit/mips/md-stubs.hpp b/src/vm/jit/mips/md-stubs.hpp
new file mode 100644 (file)
index 0000000..7451d76
--- /dev/null
@@ -0,0 +1,56 @@
+/* src/vm/jit/mips/md-stubs.hpp - MIPS JIT stubs
+
+   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 _MD_STUBS_HPP
+#define _MD_STUBS_HPP
+
+#include "config.h"
+
+
+/**
+ * Return the code size of a compiler on a MIPS architecture.
+ *
+ * @return Code size in bytes.
+ */
+int CompilerStub::get_code_size()
+{
+       return 1 * 4;
+}
+
+#endif // _MD_STUBS_HPP
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
index dbbee3249abe6a67ee770a66b72ee0bea901ca65..9ea8bd5c6350190601980e3f65ead85962566e5a 100644 (file)
@@ -53,13 +53,15 @@ enum {
 
        TRAP_ClassCastException             = 5,
        TRAP_CHECK_EXCEPTION                = 6,
-       TRAP_PATCHER                        = 7,
+       TRAP_COMPILER                       = 7,
 
        /* Don't use 8 (could be a normal load offset). */
 
-       TRAP_COMPILER                       = 9,
-       TRAP_COUNTDOWN                      = 10,
-       TRAP_END
+       TRAP_COUNTDOWN                      = 9,
+       TRAP_END,
+
+       // This is handled via SIGILL.
+       TRAP_PATCHER                        = 99 // A large number.
 };
 
 #endif /* _MD_TRAP_H */
index af5f92fc1ab74d57fd369f933311801ca4ef17bf..6a83c92da84516d42e7cbce2bf635b4c12416333 100644 (file)
@@ -37,7 +37,7 @@
 #include "vm/global.h"
 #include "vm/vm.hpp"
 
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
 
 
 /* md_jit_method_patch_address *************************************************
index 2a0a9dd9adabfc755f81247768a2f58c8e910d73..a32f18b9f24b51578aec4681844fdd494220177b 100644 (file)
 #include <assert.h>
 #include <stdint.h>
 
-#include "vm/types.h"
-
 #include "vm/jit/mips/codegen.h"
 #include "vm/jit/mips/md.h"
 
 #include "mm/memory.h"
 
-#include "native/native.h"
+#include "native/native.hpp"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/class.h"
-#include "vm/field.h"
+#include "vm/field.hpp"
 #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"
-
-
-#define PATCH_BACK_ORIGINAL_MCODE \
-       *((u4 *) pr->mpc) = (u4) pr->mcode; \
-       md_icacheflush((u1 *) pr->mpc, PATCHER_CALL_SIZE);
+#include "vm/jit/patcher-common.hpp"
 
 
 /* patcher_patch_code **********************************************************
@@ -62,7 +55,8 @@
 
 void patcher_patch_code(patchref_t *pr)
 {
-       PATCH_BACK_ORIGINAL_MCODE;
+       *((uint32_t*) pr->mpc) = (uint32_t) pr->mcode;
+       md_icacheflush((void*) pr->mpc, PATCHER_CALL_SIZE);
 }
 
 
@@ -78,36 +72,29 @@ void patcher_patch_code(patchref_t *pr)
 
 bool patcher_get_putstatic(patchref_t *pr)
 {
-       unresolved_field *uf;
-       u1               *datap;
-       fieldinfo        *fi;
-
-       /* get stuff from the stack */
-
-       uf    = (unresolved_field *) pr->ref;
-       datap = (u1 *)               pr->datap;
+       unresolved_field* uf    = (unresolved_field *) pr->ref;
+       uintptr_t*        datap = (uintptr_t*)         pr->datap;
 
-       /* get the fieldinfo */
+       // Resolve the field.
+       fieldinfo* fi = resolve_field_eager(uf);
 
-       if (!(fi = resolve_field_eager(uf)))
+       if (fi == NULL)
                return false;
 
-       /* check if the field's class is initialized */
-
+       // Check if the field's class is initialized.
        if (!(fi->clazz->state & CLASS_INITIALIZED))
                if (!initialize_class(fi->clazz))
                        return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
-
-       /* patch the field value's address */
-
-       *((intptr_t *) datap) = (intptr_t) fi->value;
-
-       /* synchronize data cache */
+       // Patch the field value's address.
+       *datap = (uintptr_t) fi->value;
 
+       // Synchronize data cache.
        md_dcacheflush(datap, SIZEOF_VOID_P);
 
+       // Patch back the original code.
+       patcher_patch_code(pr);
+
        return true;
 }
 
@@ -123,46 +110,41 @@ bool patcher_get_putstatic(patchref_t *pr)
 
 bool patcher_get_putfield(patchref_t *pr)
 {
-       u1               *ra;
-       unresolved_field *uf;
-       fieldinfo        *fi;
-
-       /* get stuff from the stack */
+       uint32_t*         pc = (uint32_t*)         pr->mpc;
+       unresolved_field* uf = (unresolved_field*) pr->ref;
 
-       ra = (u1 *)               pr->mpc;
-       uf = (unresolved_field *) pr->ref;
+       // Resolve the field.
+       fieldinfo* fi = resolve_field_eager(uf);
 
-       /* get the fieldinfo */
-
-       if (!(fi = resolve_field_eager(uf)))
+       if (fi == NULL)
                return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
-
-       /* if we show disassembly, we have to skip the nop's */
-
-       if (opt_shownops)
-               ra = ra + PATCHER_CALL_SIZE;
-
 #if SIZEOF_VOID_P == 4
        if (IS_LNG_TYPE(fi->type)) {
 # if WORDS_BIGENDIAN == 1
-               /* ATTENTION: order of these instructions depend on M_LLD_INTERN */
-               *((u4 *) (ra + 0 * 4)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
-               *((u4 *) (ra + 1 * 4)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
+               // ATTENTION: order of these instructions depend on M_LLD_INTERN.
+               // The first instruction is patched back later.
+               pr->mcode |= (int16_t) ((fi->offset + 0) & 0x0000ffff);
+               pc[1]     |= (int16_t) ((fi->offset + 4) & 0x0000ffff);
 # else
-               /* ATTENTION: order of these instructions depend on M_LLD_INTERN */
-               *((u4 *) (ra + 0 * 4)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
-               *((u4 *) (ra + 1 * 4)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
+               // ATTENTION: order of these instructions depend on M_LLD_INTERN.
+               // The first instruction is patched back later.
+               pr->mcode |= (int16_t) ((fi->offset + 4) & 0x0000ffff);
+               pc[1]     |= (int16_t) ((fi->offset + 0) & 0x0000ffff);
 # endif
        }
        else
 #endif
-               *((u4 *) (ra + 0 * 4)) |= (s2) (fi->offset & 0x0000ffff);
+       {
+               // The instruction is patched back later.
+               pr->mcode |= (int16_t) (fi->offset & 0x0000ffff);
+       }
 
-       /* synchronize instruction cache */
+       // Synchronize instruction cache.
+       md_icacheflush(pc, 2 * 4);
 
-       md_icacheflush(ra, 2 * 4);
+       // Patch back the original code.
+       patcher_patch_code(pr);
 
        return true;
 }
@@ -196,30 +178,24 @@ bool patcher_get_putfield(patchref_t *pr)
 
 bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
 {
-       constant_classref *cr;
-       u1                *datap;
-       classinfo         *c;
-
-       /* get stuff from the stack */
+       constant_classref* cr    = (constant_classref*) pr->ref;
+       uintptr_t*         datap = (uintptr_t*)         pr->datap;
 
-       cr    = (constant_classref *) pr->ref;
-       datap = (u1 *)                pr->datap;
+       // Resolve the class.
+       classinfo* c = resolve_classref_eager(cr);
 
-       /* get the classinfo */
-
-       if (!(c = resolve_classref_eager(cr)))
+       if (c == NULL)
                return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
-
-       /* patch the classinfo pointer */
-
-       *((intptr_t *) datap) = (intptr_t) c;
-
-       /* synchronize data cache */
+       // Patch the class.
+       *datap = (uintptr_t) c;
 
+       // Synchronize data cache.
        md_dcacheflush(datap, SIZEOF_VOID_P);
 
+       // Patch back the original code.
+       patcher_patch_code(pr);
+
        return true;
 }
 
@@ -237,30 +213,24 @@ bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
 
 bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
 {
-       constant_classref *cr;
-       u1                *datap;
-       classinfo         *c;
-
-       /* get stuff from the stack */
+       constant_classref* cr    = (constant_classref *) pr->ref;
+       uintptr_t*         datap = (uintptr_t*)          pr->datap;
 
-       cr    = (constant_classref *) pr->ref;
-       datap = (u1 *)                pr->datap;
+       // Resolve the field.
+       classinfo* c = resolve_classref_eager(cr);
 
-       /* get the fieldinfo */
-
-       if (!(c = resolve_classref_eager(cr)))
+       if (c == NULL)
                return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
-
-       /* patch super class' vftbl */
-
-       *((intptr_t *) datap) = (intptr_t) c->vftbl;
-
-       /* synchronize data cache */
+       // Patch super class' vftbl.
+       *datap = (uintptr_t) c->vftbl;
 
+       // Synchronize data cache.
        md_dcacheflush(datap, SIZEOF_VOID_P);
 
+       // Patch back the original code.
+       patcher_patch_code(pr);
+
        return true;
 }
 
@@ -279,30 +249,24 @@ bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
 
 bool patcher_resolve_classref_to_flags(patchref_t *pr)
 {
-       constant_classref *cr;
-       u1                *datap;
-       classinfo         *c;
-
-       /* get stuff from the stack */
+       constant_classref* cr    = (constant_classref*) pr->ref;
+       int32_t*           datap = (int32_t*)           pr->datap;
 
-       cr    = (constant_classref *) pr->ref;
-       datap = (u1 *)                pr->datap;
+       // Resolve the class.
+       classinfo* c = resolve_classref_eager(cr);
 
-       /* get the fieldinfo */
-
-       if (!(c = resolve_classref_eager(cr)))
+       if (c == NULL)
                return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
-
-       /* patch class flags */
-
-       *((int32_t *) datap) = (int32_t) c->flags;
-
-       /* synchronize data cache */
+       // Patch class flags.
+       *datap = (int32_t) c->flags;
 
+       // Synchronize data cache.
        md_dcacheflush(datap, sizeof(int32_t));
 
+       // Patch back the original code.
+       patcher_patch_code(pr);
+
        return true;
 }
 
@@ -320,30 +284,24 @@ bool patcher_resolve_classref_to_flags(patchref_t *pr)
 
 bool patcher_invokestatic_special(patchref_t *pr)
 {
-       unresolved_method *um;
-       u1                *datap;
-       methodinfo        *m;
-
-       /* get stuff from the stack */
+       unresolved_method* um    = (unresolved_method*) pr->ref;
+       void**             datap = (void*)              pr->datap;
 
-       um    = (unresolved_method *) pr->ref;
-       datap = (u1 *)                pr->datap;
+       // Resolve the method.
+       methodinfo* m = resolve_method_eager(um);
 
-       /* get the fieldinfo */
-
-       if (!(m = resolve_method_eager(um)))
+       if (m == NULL)
                return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
-
-       /* patch stubroutine */
-
-       *((ptrint *) datap) = (ptrint) m->stubroutine;
-
-       /* synchronize data cache */
+       // Patch stubroutine.
+       *datap = (void*) m->stubroutine;
 
+       // Synchronize data cache.
        md_dcacheflush(datap, SIZEOF_VOID_P);
 
+       // Patch back the original code.
+       patcher_patch_code(pr);
+
        return true;
 }
 
@@ -362,36 +320,23 @@ bool patcher_invokestatic_special(patchref_t *pr)
 
 bool patcher_invokevirtual(patchref_t *pr)
 {
-       u1                *ra;
-       unresolved_method *um;
-       methodinfo        *m;
-
-       /* get stuff from the stack */
+       uint32_t*          pc = (uint32_t*)          pr->mpc;
+       unresolved_method* um = (unresolved_method*) pr->ref;
 
-       ra = (u1 *)                pr->mpc;
-       um = (unresolved_method *) pr->ref;
+       // Resolve the method.
+       methodinfo* m = resolve_method_eager(um);
 
-       /* get the fieldinfo */
-
-       if (!(m = resolve_method_eager(um)))
+       if (m == NULL)
                return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
-
-       /* if we show disassembly, we have to skip the nop's */
-
-       if (opt_shownops)
-               ra = ra + PATCHER_CALL_SIZE;
-
-       /* patch vftbl index */
+       // Patch vftbl index.
+       pc[1] |= (int32_t) ((OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex) & 0x0000ffff);
 
-       *((s4 *) (ra + 1 * 4)) |=
-               (s4) ((OFFSET(vftbl_t, table[0]) +
-                          sizeof(methodptr) * m->vftblindex) & 0x0000ffff);
+       // Synchronize instruction cache.
+       md_icacheflush(pc + 1, 1 * 4);
 
-       /* synchronize instruction cache */
-
-       md_icacheflush(ra + 1 * 4, 1 * 4);
+       // Patch back the original code.
+       patcher_patch_code(pr);
 
        return true;
 }
@@ -412,41 +357,26 @@ bool patcher_invokevirtual(patchref_t *pr)
 
 bool patcher_invokeinterface(patchref_t *pr)
 {
-       u1                *ra;
-       unresolved_method *um;
-       methodinfo        *m;
-
-       /* get stuff from the stack */
+       uint32_t*          pc = (uint32_t*)          pr->mpc;
+       unresolved_method* um = (unresolved_method*) pr->ref;
 
-       ra = (u1 *)                pr->mpc;
-       um = (unresolved_method *) pr->ref;
+       // Resovlve the method.
+       methodinfo* m = resolve_method_eager(um);
 
-       /* get the fieldinfo */
-
-       if (!(m = resolve_method_eager(um)))
+       if (m == NULL)
                return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
-
-       /* if we show disassembly, we have to skip the nop's */
+       // Patch interfacetable index.
+       pc[1] |= (int32_t) ((OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr*) * m->clazz->index) & 0x0000ffff);
 
-       if (opt_shownops)
-               ra = ra + PATCHER_CALL_SIZE;
+       // Patch method offset.
+       pc[2] |= (int32_t) ((sizeof(methodptr) * (m - m->clazz->methods)) & 0x0000ffff);
 
-       /* patch interfacetable index */
+       // Synchronize instruction cache.
+       md_icacheflush(pc + 1, 2 * 4);
 
-       *((s4 *) (ra + 1 * 4)) |=
-               (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
-                          sizeof(methodptr*) * m->clazz->index) & 0x0000ffff);
-
-       /* patch method offset */
-
-       *((s4 *) (ra + 2 * 4)) |=
-               (s4) ((sizeof(methodptr) * (m - m->clazz->methods)) & 0x0000ffff);
-
-       /* synchronize instruction cache */
-
-       md_icacheflush(ra + 1 * 4, 2 * 4);
+       // Patch back the original code.
+       patcher_patch_code(pr);
 
        return true;
 }
@@ -468,39 +398,24 @@ bool patcher_invokeinterface(patchref_t *pr)
 
 bool patcher_checkcast_interface(patchref_t *pr)
 {
-       u1                *ra;
-       constant_classref *cr;
-       classinfo         *c;
+       uint32_t*          pc = (uint32_t*)          pr->mpc;
+       constant_classref* cr = (constant_classref*) pr->ref;
 
-       /* get stuff from the stack */
+       // Resolve the class.
+       classinfo* c = resolve_classref_eager(cr);
 
-       ra = (u1 *)                pr->mpc;
-       cr = (constant_classref *) pr->ref;
-
-       /* get the fieldinfo */
-
-       if (!(c = resolve_classref_eager(cr)))
+       if (c == NULL)
                return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
-
-       /* if we show disassembly, we have to skip the nop's */
-
-       if (opt_shownops)
-               ra = ra + PATCHER_CALL_SIZE;
+       // Patch super class index.
+       pc[2] |= (int32_t) (-(c->index) & 0x0000ffff);
+       pc[6] |= (int32_t) ((OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*)) & 0x0000ffff);
 
-       /* patch super class index */
+       // Synchronize instruction cache.
+       md_icacheflush(pc + 2, 5 * 4);
 
-       *((s4 *) (ra + 2 * 4)) |= (s4) (-(c->index) & 0x0000ffff);
-       /*      *((s4 *) (ra + 5 * 4)) |= (s4) ((OFFSET(vftbl_t, interfacetable[0]) - */
-       /*                                                                       c->index * sizeof(methodptr*)) & 0x0000ffff); */
-       *((s4 *) (ra + 6 * 4)) |=
-               (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
-                          c->index * sizeof(methodptr*)) & 0x0000ffff);
-
-       /* synchronize instruction cache */
-
-       md_icacheflush(ra + 2 * 4, 5 * 4);
+       // Patch back the original code.
+       patcher_patch_code(pr);
 
        return true;
 }
@@ -522,37 +437,24 @@ bool patcher_checkcast_interface(patchref_t *pr)
 
 bool patcher_instanceof_interface(patchref_t *pr)
 {
-       u1                *ra;
-       constant_classref *cr;
-       classinfo         *c;
-
-       /* get stuff from the stack */
-
-       ra = (u1 *)                pr->mpc;
-       cr = (constant_classref *) pr->ref;
+       uint32_t*          pc = (uint32_t*)          pr->mpc;
+       constant_classref* cr = (constant_classref*) pr->ref;
 
-       /* get the fieldinfo */
+       // Resolve the method.
+       classinfo* c = resolve_classref_eager(cr);
 
-       if (!(c = resolve_classref_eager(cr)))
+       if (c == NULL)
                return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
-
-       /* if we show disassembly, we have to skip the nop's */
-
-       if (opt_shownops)
-               ra = ra + PATCHER_CALL_SIZE;
-
-       /* patch super class index */
-
-       *((s4 *) (ra + 2 * 4)) |= (s4) (-(c->index) & 0x0000ffff);
-       *((s4 *) (ra + 5 * 4)) |=
-               (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
-                          c->index * sizeof(methodptr*)) & 0x0000ffff);
+       // Patch super class index.
+       pc[2] |= (int32_t) (-(c->index) & 0x0000ffff);
+       pc[5] |= (int32_t) ((OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*)) & 0x0000ffff);
 
-       /* synchronize instruction cache */
+       // Synchronize instruction cache.
+       md_icacheflush(pc + 2, 4 * 4);
 
-       md_icacheflush(ra + 2 * 4, 4 * 4);
+       // Patch back the original code.
+       patcher_patch_code(pr);
 
        return true;
 }
index ddf3d930f44b4d2b5fcf2698ce4280009e54b6dd..36e97a77f99a7bcfd8723c4b88a97690fe8309d7 100644 (file)
 
 */
 
-
 #include "config.h"
 
 #include "mm/memory.h"
 
-#include "vm/jit/code.h"
+#include "vm/jit/code.hpp"
 #include "vm/jit/oprofile-agent.hpp"
 
 #include <string.h>
@@ -94,15 +93,6 @@ void OprofileAgent::close()
 
        _handle = 0;
 }
-/* Legacy C interface *********************************************************/
-
-extern "C" {
-
-void OprofileAgent_initialize() { OprofileAgent::initialize(); }
-void OprofileAgent_newmethod(methodinfo *m) { OprofileAgent::newmethod(m); }
-void OprofileAgent_close() { OprofileAgent::close(); }
-
-}
 
 /*
  * These are local overrides for various environment variables in Emacs.
index 9b8cbdb5d2d9dcfcb5e09c8d2be4e8f980e9fd0e..14bc54968ca41958a206f86673049a1aef5c90d4 100644 (file)
 
 #include "config.h"
 
-#ifdef __cplusplus
 extern "C" {
-#endif
 
 #include "vm/method.h"
-
 #include <opagent.h>
 
-#ifdef __cplusplus
 }
-#endif
-
-#ifdef __cplusplus
 
 class OprofileAgent
 {
@@ -54,18 +47,6 @@ public:
        static void close();
 };
 
-#else
-
-/* Legacy C interface *********************************************************/
-
-typedef struct OprofileAgent OprofileAgent;
-
-void  OprofileAgent_initialize(void);
-void  OprofileAgent_newmethod(methodinfo *);
-void  OprofileAgent_close();
-
-#endif
-
 #endif /* _OPROFILE_AGENT_HPP */
 
 
index b7c937c13cec6cf9c5c3476d9433de7330937387..d725afc4dcab935461547a33580796c7f889250c 100644 (file)
@@ -1,9 +1,7 @@
 ## src/vm/jit/optimizing/Makefile.am
 ##
-## Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel, C. Oates,
-## R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
-## C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
-## Institut f. Computersprachen - TU Wien
+## Copyright (C) 1996-2005, 2006, 2007, 2008
+## CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 ##
 ## This file is part of CACAO.
 ##
@@ -44,9 +42,9 @@ REORDER_SOURCES = \
 endif
 
 if ENABLE_THREADS
-RECOMPILE_SOURCES = \
-       recompile.c \
-       recompile.h
+RECOMPILER_SOURCES = \
+       recompiler.cpp \
+       recompiler.hpp
 endif
 
 if ENABLE_SSA
@@ -61,8 +59,8 @@ SSA_SOURCES = \
        ssa_rename.h \
        graph.c \
        graph.h \
-       dominators.c \
-       dominators.h \
+       dominators.cpp \
+       dominators.hpp \
        lifetimes.c \
        lifetimes.h \
        ssa2.c \
@@ -82,7 +80,7 @@ noinst_LTLIBRARIES = \
 liboptimizing_la_SOURCES = \
        $(IFCONV_SOURCES) \
        $(PROFILE_SOURCES) \
-       $(RECOMPILE_SOURCES) \
+       $(RECOMPILER_SOURCES) \
        $(REORDER_SOURCES) \
        $(SSA_SOURCES) \
        $(ESCAPE_SOURCES)
index 70b942431c92042f32d43a5d841527f78361dc87..ac9456ab0b40f90a50ad232567b4a36ea7b3c6c4 100644 (file)
@@ -25,7 +25,9 @@
 
 #include "config.h"
 
-#include "mm/dumpmemory.h"
+#include <stdint.h>
+
+#include "mm/dumpmemory.hpp"
 #include "mm/memory.h"
 
 #include "toolbox/bitvector.h"
diff --git a/src/vm/jit/optimizing/dominators.c b/src/vm/jit/optimizing/dominators.c
deleted file mode 100644 (file)
index 3fcf46f..0000000
+++ /dev/null
@@ -1,654 +0,0 @@
-/* src/vm/jit/optimizing/dominators.c - dominators and dominance frontier
-
-   Copyright (C) 2005, 2006, 2008
-   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
-
-   This file is part of CACAO.
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2, or (at
-   your option) any later version.
-
-   This program is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-   02111-1307, USA.
-
-*/
-
-
-#include "mm/memory.h"
-
-#include "toolbox/bitvector.h"
-
-#include "vm/jit/jit.h"
-
-#include "vm/jit/optimizing/graph.h"
-#include "vm/jit/optimizing/dominators.h"
-
-/* function prototypes */
-void dom_Dominators_init(dominatordata *dd, int basicblockcount);
-#ifdef DOM_DEBUG_CHECK
-int dom_AncestorWithLowestSemi(dominatordata *dd, int v, int basicblockcount);
-void dom_Link(dominatordata *dd, int p, int n, int basicblockcount);
-void dom_DFS(graphdata *gd, dominatordata *dd, int p, int n, int *N,
-                        int basicblockcount);
-#else
-int dom_AncestorWithLowestSemi(dominatordata *dd, int v);
-void dom_Link(dominatordata *dd, int p, int n);
-void dom_DFS(graphdata *gd, dominatordata *dd, int p, int n, int *N);
-#endif
-
-/*************************************
-Calculate Dominators
-*************************************/
-dominatordata *compute_Dominators(graphdata *gd, int basicblockcount) {
-       int i,j,n,N,p,s,s_,v,y;
-       graphiterator iter;
-       dominatordata *dd;
-
-       dd = DNEW(dominatordata);
-
-       dom_Dominators_init(dd, basicblockcount);
-       
-       N=0;
-
-       /* 1 ist the root node of the method                    */
-       /* 0 is the artificial parent, where locals are set to their parameters */
-       dom_DFS(gd, dd, -1, 0, &N
-#ifdef DOM_DEBUG_CHECK
-                       ,basicblockcount
-#endif
-                       );
-
-       for(i = N-1; i > 0; i--) {
-               _DOM_CHECK_BOUNDS(i, 0, basicblockcount);
-               n = dd->vertex[i];
-               _DOM_CHECK_BOUNDS(n, 0, basicblockcount);
-               p = dd->parent[n];
-               s = p;
-               j = graph_get_first_predecessor(gd, n, &iter);
-               for (; j != -1; j = graph_get_next(&iter)) {
-               _DOM_CHECK_BOUNDS(j, 0, basicblockcount);
-                       if (dd->dfnum[j] <= dd->dfnum[n])
-                               s_ = j;
-                       else
-                               s_ = dd->semi[dom_AncestorWithLowestSemi(dd, j
-#ifdef DOM_DEBUG_CHECK
-                                                                                                                ,basicblockcount
-#endif
-                                                                                                                )];
-               _DOM_CHECK_BOUNDS(s_, 0, basicblockcount);
-               _DOM_CHECK_BOUNDS(s, 0, basicblockcount);
-                       if (dd->dfnum[s_] < dd->dfnum[s])
-                               s = s_;
-               }
-               dd->semi[n] = s;
-               _DOM_CHECK_BOUNDS(dd->num_bucket[s], 0, basicblockcount);
-               dd->bucket[s][dd->num_bucket[s]] = n;
-               dd->num_bucket[s]++;
-               dom_Link(dd, p, n
-#ifdef DOM_DEBUG_CHECK
-                                , basicblockcount
-#endif
-                                );
-               _DOM_CHECK_BOUNDS(p, 0, basicblockcount);
-               for(j = 0; j < dd->num_bucket[p]; j++) {
-               _DOM_CHECK_BOUNDS(j, 0, basicblockcount);
-                       v = dd->bucket[p][j];
-                       y = dom_AncestorWithLowestSemi(dd, v
-#ifdef DOM_DEBUG_CHECK
-                                                                                  , basicblockcount
-#endif
-                                                                                  );
-               _DOM_CHECK_BOUNDS(y, 0, basicblockcount);
-               _DOM_CHECK_BOUNDS(v, 0, basicblockcount);
-           if (dd->semi[y] == dd->semi[v])
-                               dd->idom[v] = p;
-                       else
-                               dd->samedom[v] = y;
-               }
-               dd->num_bucket[p] = 0;
-       }
-       for(i = 1; i < N; i++) {
-               n = dd->vertex[i];
-               _DOM_CHECK_BOUNDS(n, 0, basicblockcount);
-           if (dd->samedom[n] != -1) {
-                       _DOM_CHECK_BOUNDS(dd->samedom[n], 0, basicblockcount);
-                       dd->idom[n] = dd->idom[dd->samedom[n]];
-               }
-       }
-       return dd;
-}
-
-/********************************************
-compute Dominace Frontier
-********************************************/
-void computeDF(graphdata *gd, dominatordata *dd, int basicblockcount, int n) {
-       int c,i,j;
-       bool *_S;
-       graphiterator iter;
-
-       _S = DMNEW(bool, basicblockcount);
-       for(i = 0; i < basicblockcount; i++)
-               _S[i] = false;
-       i = graph_get_first_successor(gd, n, &iter);
-       for (; i != -1; i = graph_get_next(&iter)) {
-               _DOM_CHECK_BOUNDS(i, 0, basicblockcount);
-               if (dd->idom[i] != n)
-                       _S[i] = true;
-       }
-       for(c=0; c < basicblockcount; c++) {
-               if (dd->idom[c] == n) {
-                       computeDF(gd, dd, basicblockcount, c);
-                       for(j=0; j < dd->num_DF[c]; j++) {
-               _DOM_CHECK_BOUNDS(dd->DF[c][j], 0, basicblockcount);
-                   if (n != dd->idom[dd->DF[c][j]])
-                                       /* n does not dominate DF[c][j] -> traverse idom list? */
-                                       _S[dd->DF[c][j]] = true;
-                       }
-               }
-       }
-       for(i = 0; i < basicblockcount; i++)
-               if (_S[i]) {
-               _DOM_CHECK_BOUNDS(dd->num_DF[n], 0, basicblockcount);
-                       dd->DF[n][dd->num_DF[n]] = i;
-                       dd->num_DF[n]++;
-               }
-}
-
-
-void dom_Dominators_init(dominatordata *dd, int basicblockcount) {
-       int i;
-
-       dd->dfnum  = DMNEW(int, basicblockcount);
-       dd->vertex = DMNEW(int, basicblockcount);
-       dd->parent = DMNEW(int, basicblockcount);
-       dd->semi   = DMNEW(int, basicblockcount);
-       dd->ancestor = DMNEW(int, basicblockcount);
-       dd->idom     = DMNEW(int, basicblockcount);
-       dd->samedom  = DMNEW(int, basicblockcount);
-       dd->bucket   = DMNEW(int*, basicblockcount);
-       dd->num_bucket = DMNEW(int, basicblockcount);
-       dd->DF       = DMNEW(int*, basicblockcount);
-       dd->num_DF   = DMNEW(int, basicblockcount);
-       dd->best     = DMNEW(int, basicblockcount);
-       for (i=0; i < basicblockcount; i++) {
-               dd->dfnum[i] = -1;
-               dd->semi[i] = dd->ancestor[i] = dd->idom[i] = dd->samedom[i] = -1;
-               dd->num_bucket[i] = 0;
-               dd->bucket[i] = DMNEW(int, basicblockcount);
-               dd->num_DF[i] = 0;
-               dd->DF[i] = DMNEW(int, basicblockcount);
-       }
-}
-
-/**************************************
-Create Depth First Spanning Tree
-**************************************/
-#ifdef DOM_DEBUG_CHECK
-void dom_DFS(graphdata *gd, dominatordata *dd, int p, int n, int *N,
-                        int basicblockcount) {
-#else
-void dom_DFS(graphdata *gd, dominatordata *dd, int p, int n, int *N) {
-#endif
-    int i;
-       graphiterator iter;
-
-       _DOM_CHECK_BOUNDS(n,0,basicblockcount);
-       if (dd->dfnum[n] == -1) { /* not visited till now? */
-               dd->dfnum[n] = *N;
-               _DOM_CHECK_BOUNDS(*N,0,basicblockcount);
-               dd->vertex[*N] = n;
-               dd->parent[n] = p;
-               (*N)++;
-               i = graph_get_first_successor(gd, n, &iter);
-               for (; i != -1; i = graph_get_next(&iter)) {
-                       dom_DFS(gd, dd, n, i, N
-#ifdef DOM_DEBUG_CHECK
-                                       , basicblockcount
-#endif
-                                       );
-               }
-       }
-}
-
-#ifdef DOM_DEBUG_CHECK
-int dom_AncestorWithLowestSemi(dominatordata *dd, int v, int basicblockcount) {
-#else
-int dom_AncestorWithLowestSemi(dominatordata *dd, int v) {
-#endif
-       int a,b;
-
-       _DOM_CHECK_BOUNDS(v, 0, basicblockcount);
-       a = dd->ancestor[v];
-       _DOM_CHECK_BOUNDS(a,0,basicblockcount);
-       if (dd->ancestor[a] != -1) {
-               b = dom_AncestorWithLowestSemi(dd, a
-#ifdef DOM_DEBUG_CHECK
-                                                                          , basicblockcount
-#endif
-                                                                          );
-               dd->ancestor[v] = dd->ancestor[a];
-               _DOM_CHECK_BOUNDS(b,0,basicblockcount);
-               _DOM_CHECK_BOUNDS(dd->best[v],0,basicblockcount);
-               _DOM_CHECK_BOUNDS(dd->semi[dd->best[v]],0,basicblockcount);
-               if (dd->dfnum[dd->semi[b]] < dd->dfnum[dd->semi[dd->best[v]]])
-                       dd->best[v] = b;
-       }
-       return dd->best[v];
-}
-
-#ifdef DOM_DEBUG_CHECK
-void dom_Link(dominatordata *dd, int p, int n, int basicblockcount) {
-#else
-void dom_Link(dominatordata *dd, int p, int n) {
-#endif
-       _DOM_CHECK_BOUNDS(n,0,basicblockcount);
-       dd->ancestor[n] = p;
-       dd->best[n] = n;
-}
-
-/*********************************************************/
-
-typedef struct basicblock_info basicblock_info;
-
-struct basicblock_info {
-       basicblock *bb;
-       int dfnum;
-       basicblock_info *parent;
-       basicblock_info *semi;
-       basicblock_info *ancestor;
-       basicblock_info *best;
-       basicblock_info *idom;
-       basicblock_info *samedom;
-       basicblock_info **bucket;
-       unsigned bucketcount;
-};
-
-typedef struct dominator_tree_info dominator_tree_info;
-
-struct dominator_tree_info {
-       jitdata *jd;
-       basicblock_info *basicblocks;
-       basicblock_info **df_map;
-       unsigned df_counter;
-};
-
-static dominator_tree_info *dominator_tree_init(jitdata *jd) {
-       dominator_tree_info *di;
-       basicblock *itb;
-       basicblock_info *iti;
-
-       di = DNEW(dominator_tree_info);
-
-       di->jd = jd;
-
-       di->basicblocks = DMNEW(basicblock_info, jd->basicblockcount);
-       MZERO(di->basicblocks, basicblock_info, jd->basicblockcount);
-       
-       for (iti = di->basicblocks; iti != di->basicblocks + jd->basicblockcount; ++iti) {
-               iti->dfnum = -1;
-               iti->bucket = DMNEW(basicblock_info *, jd->basicblockcount);
-               iti->bucketcount = 0;
-       }
-
-       for (itb = jd->basicblocks; itb; itb = itb->next) {
-               di->basicblocks[itb->nr].bb = itb;
-       }
-
-       di->df_map = DMNEW(basicblock_info *, jd->basicblockcount);
-       MZERO(di->df_map, basicblock_info *, jd->basicblockcount);
-
-       di->df_counter = 0;
-
-       return di;
-}
-
-inline basicblock_info *dominator_tree_get_basicblock(dominator_tree_info *di, basicblock *bb) {
-       return di->basicblocks + bb->nr;
-}
-
-static void dominator_tree_depth_first_search(
-       dominator_tree_info *di, basicblock_info *parent, basicblock_info *node
-) {
-       basicblock **it;
-
-       if (node->dfnum == -1) {
-
-               node->dfnum = di->df_counter;
-               node->parent = parent;
-               di->df_map[di->df_counter] = node;
-               di->df_counter += 1;
-
-               for (it = node->bb->successors; it != node->bb->successors + node->bb->successorcount; ++it) {
-                       dominator_tree_depth_first_search(
-                               di, node, 
-                               dominator_tree_get_basicblock(di, *it)
-                       );
-               }
-       }
-}
-
-void dominator_tree_link(dominator_tree_info *di, basicblock_info *parent, basicblock_info *node) {
-       node->ancestor = parent;
-       node->best = node;
-}
-
-basicblock_info *dominator_tree_ancestor_with_lowest_semi(
-       dominator_tree_info *di, basicblock_info *node
-) {
-       basicblock_info *a, *b;
-
-       a = node->ancestor;
-
-       if (a->ancestor != NULL) {
-               b = dominator_tree_ancestor_with_lowest_semi(di, a);
-               node->ancestor = a->ancestor;
-               if (b->semi->dfnum < node->best->semi->dfnum) {
-                       node->best = b;
-               }
-       }
-
-       return node->best;
-}
-
-void dominator_tree_build_intern(jitdata *jd) {
-       
-       dominator_tree_info *di;
-       basicblock_info *node;
-       basicblock_info *semicand;
-       basicblock_info *pred;
-       basicblock **itb;
-       basicblock_info **itii;
-       basicblock_info *v, *y;
-       int i;
-
-       di = dominator_tree_init(jd);
-
-       dominator_tree_depth_first_search(di, NULL, dominator_tree_get_basicblock(di, jd->basicblocks));
-
-       for (i = di->df_counter - 1; i >= 1; --i) {
-               node = di->df_map[i];
-
-               node->semi = node->parent;
-
-               for (
-                       itb = node->bb->predecessors; 
-                       itb != node->bb->predecessors + node->bb->predecessorcount; 
-                       ++itb
-               ) {
-
-                       pred = dominator_tree_get_basicblock(di, *itb);
-
-                       if (pred->dfnum <= node->dfnum) {
-                               semicand = pred;
-                       } else {
-                               semicand = dominator_tree_ancestor_with_lowest_semi(di, pred)->semi;
-                       }
-
-                       if (semicand->dfnum < node->semi->dfnum) {
-                               node->semi = semicand;
-                       }
-               }
-
-               node->semi->bucket[node->semi->bucketcount] = node;
-               node->semi->bucketcount += 1;
-
-               dominator_tree_link(di, node->parent, node);
-
-               for (itii = node->parent->bucket; itii != node->parent->bucket + node->parent->bucketcount; ++itii) {
-                       v = *itii;
-                       y = dominator_tree_ancestor_with_lowest_semi(di, v);
-                       if (y->semi == v->semi) {
-                               v->idom = node->parent;
-                       } else {
-                               v->samedom = y;
-                       }
-               }
-
-               node->parent->bucketcount = 0;
-       }
-
-       for (i = 1; i < di->df_counter; ++i) {
-               node = di->df_map[i];
-               if (node->samedom) {
-                       node->idom = node->samedom->idom;
-               }
-
-               node->bb->idom = node->idom->bb;
-               node->idom->bb->domsuccessorcount += 1;
-       }
-}
-
-void dominator_tree_link_children(jitdata *jd) {
-       basicblock *bb;
-       int32_t ds;
-       /* basicblock number => current number of successors */
-       unsigned *numsuccessors;
-
-       /* Allocate memory for successors */
-
-       for (bb = jd->basicblocks; bb; bb = bb->next) {
-               if (bb->domsuccessorcount > 0) {
-                       bb->domsuccessors = DMNEW(basicblock *, bb->domsuccessorcount);
-               }
-       }
-
-       /* Allocate memory for per basic block counter of successors */
-
-       ds = dumpmemory_marker();
-       numsuccessors = DMNEW(unsigned, jd->basicblockcount);
-       MZERO(numsuccessors, unsigned, jd->basicblockcount);
-
-       /* Link immediate dominators with successors */
-
-       for (bb = jd->basicblocks; bb; bb = bb->next) {
-               if (bb->idom) {
-                       bb->idom->domsuccessors[numsuccessors[bb->idom->nr]] = bb;
-                       numsuccessors[bb->idom->nr] += 1;
-               }
-       }
-
-       /* Free memory */
-
-       dumpmemory_release(ds);
-}
-
-bool dominator_tree_build(jitdata *jd) {
-       int32_t ds;
-       
-       ds = dumpmemory_marker();
-       dominator_tree_build_intern(jd);
-       dumpmemory_release(ds);
-
-       dominator_tree_link_children(jd);
-
-       return true;
-}
-
-typedef struct dominance_frontier_item dominance_frontier_item;
-
-struct dominance_frontier_item {
-       basicblock *bb;
-       dominance_frontier_item *next;
-};
-
-typedef struct dominance_frontier_list dominance_frontier_list;
-
-struct dominance_frontier_list {
-       dominance_frontier_item *first;
-       unsigned count;
-};
-
-void dominance_frontier_list_add(dominance_frontier_list *list, basicblock *bb) {
-       dominance_frontier_item *item;
-       
-       for (item = list->first; item; item = item->next) {
-               if (item->bb == bb) return;
-       }
-
-       item = DNEW(dominance_frontier_item);
-       item->bb = bb;
-       item->next = list->first;
-       list->first = item;
-       list->count += 1;
-}
-
-typedef struct dominance_frontier_info dominance_frontier_info;
-
-struct dominance_frontier_info {
-       jitdata *jd;
-       dominance_frontier_list *map;
-};
-
-dominance_frontier_info *dominance_frontier_init(jitdata *jd) {
-       dominance_frontier_info *dfi = DNEW(dominance_frontier_info);
-
-       dfi->jd = jd;
-
-       dfi->map = DMNEW(dominance_frontier_list, jd->basicblockcount);
-       MZERO(dfi->map, dominance_frontier_list, jd->basicblockcount);
-
-       return dfi;
-}
-
-bool dominance_frontier_dominates(basicblock *d, basicblock *x) {
-       x = x->idom;
-
-       while (x != NULL) {
-               if (x == d) {
-                       return true;
-               }
-               x = x->idom;
-       }
-
-       return false;
-}
-
-void dominance_frontier_for_block(dominance_frontier_info *dfi, basicblock *b) {
-       basicblock **it;
-       dominance_frontier_item *itdf;
-       dominance_frontier_list s = { NULL, 0 };
-
-       for (it = b->successors; it != b->successors + b->successorcount; ++it) {
-               if ((*it)->idom != b) {
-                       dominance_frontier_list_add(&s, *it);
-               }
-       }
-
-       for (it = b->domsuccessors; it != b->domsuccessors + b->domsuccessorcount; ++it) {
-               dominance_frontier_for_block(dfi, *it);
-               for (itdf = dfi->map[(*it)->nr].first; itdf; itdf = itdf->next) {
-                       if (! dominance_frontier_dominates(b, itdf->bb)) {
-                               dominance_frontier_list_add(&s, itdf->bb);
-                       }
-               }
-       }
-
-       dfi->map[b->nr] = s;
-}
-
-void dominance_frontier_store(dominance_frontier_info *dfi) {
-       basicblock *bb;
-       dominance_frontier_item *itdf;
-       basicblock **itout;
-
-       for (bb = dfi->jd->basicblocks; bb; bb = bb->next) {
-               if (bb->nr < dfi->jd->basicblockcount) {
-                       if (dfi->map[bb->nr].count > 0) {
-                               bb->domfrontiercount = dfi->map[bb->nr].count;
-                               itout = bb->domfrontier = DMNEW(basicblock *, bb->domfrontiercount);
-                               for (itdf = dfi->map[bb->nr].first; itdf; itdf = itdf->next) {
-                                       *itout = itdf->bb;
-                                       itout += 1;
-                               }
-                       }
-               }
-       }
-}
-
-bool dominance_frontier_build(jitdata *jd) {
-       int32_t ds = dumpmemory_marker();
-
-       dominance_frontier_info *dfi = dominance_frontier_init(jd);
-       dominance_frontier_for_block(dfi, jd->basicblocks);
-       dominance_frontier_store(dfi);
-}
-
-#include "vm/jit/show.h"
-#include "vm/jit/python.h"
-
-extern void graph_add_edge( graphdata *gd, int from, int to );
-
-void dominator_tree_validate(jitdata *jd, dominatordata *_dd) {
-       int32_t ds = dumpmemory_marker();
-       graphdata *gd;
-       int i, j;
-       basicblock *bptr, **it;
-       dominatordata *dd;
-       int *itnr;
-       bool found;
-
-       fprintf(stderr, "%s/%s: \n", jd->m->clazz->name->text, jd->m->name->text);
-       gd = graph_init(jd->basicblockcount);
-
-       for (bptr = jd->basicblocks; bptr; bptr = bptr->next) {
-               for (it = bptr->successors; it != bptr->successors + bptr->successorcount; ++it) {
-                       graph_add_edge(gd, bptr->nr, (*it)->nr);
-               }
-       }
-
-       dd = compute_Dominators(gd, jd->basicblockcount);
-
-       for (bptr = jd->basicblocks; bptr; bptr = bptr->next) {
-               if (bptr->flags >= BBREACHED) {
-                       if (bptr->idom == NULL) {
-                               if (!(dd->idom[bptr->nr] == -1)) {
-                                       printf("-- %d %d\n", dd->idom[bptr->nr], bptr->nr);
-                                       assert(0);
-                               }
-                       } else {
-                               assert(dd->idom[bptr->nr] == bptr->idom->nr);
-                       }
-               }
-       }
-
-       computeDF(gd, dd, jd->basicblockcount, 0);
-
-       for (bptr = jd->basicblocks; bptr; bptr = bptr->next) {
-               if (bptr->flags >= BBREACHED) {
-                       assert(bptr->domfrontiercount == dd->num_DF[bptr->nr]);
-                       for (itnr = dd->DF[bptr->nr]; itnr != dd->DF[bptr->nr] + dd->num_DF[bptr->nr]; ++itnr) {
-                               found = false;
-                               for (it = bptr->domfrontier; it != bptr->domfrontier + bptr->domfrontiercount; ++it) {
-                                       if ((*it)->nr == *itnr) {
-                                               found =true; break;
-                                       }
-                               }
-                               assert(found);
-                       }
-               }
-       }
-
-       dumpmemory_release(ds);
-}
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- */
diff --git a/src/vm/jit/optimizing/dominators.cpp b/src/vm/jit/optimizing/dominators.cpp
new file mode 100644 (file)
index 0000000..9fe830b
--- /dev/null
@@ -0,0 +1,657 @@
+/* src/vm/jit/optimizing/dominators.cpp - dominators and dominance frontier
+
+   Copyright (C) 2005, 2006, 2008
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+   This file is part of CACAO.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.
+
+*/
+
+
+#include "config.h"
+
+#include "config.h"
+
+#include "mm/memory.h"
+
+#include "toolbox/bitvector.h"
+
+#include "vm/jit/jit.hpp"
+
+#include "vm/jit/optimizing/graph.h"
+#include "vm/jit/optimizing/dominators.hpp"
+
+
+/* function prototypes */
+void dom_Dominators_init(dominatordata *dd, int basicblockcount);
+#ifdef DOM_DEBUG_CHECK
+int dom_AncestorWithLowestSemi(dominatordata *dd, int v, int basicblockcount);
+void dom_Link(dominatordata *dd, int p, int n, int basicblockcount);
+void dom_DFS(graphdata *gd, dominatordata *dd, int p, int n, int *N,
+                        int basicblockcount);
+#else
+int dom_AncestorWithLowestSemi(dominatordata *dd, int v);
+void dom_Link(dominatordata *dd, int p, int n);
+void dom_DFS(graphdata *gd, dominatordata *dd, int p, int n, int *N);
+#endif
+
+/*************************************
+Calculate Dominators
+*************************************/
+dominatordata *compute_Dominators(graphdata *gd, int basicblockcount) {
+       int i,j,n,N,p,s,s_,v,y;
+       graphiterator iter;
+       dominatordata *dd;
+
+       dd = (dominatordata*) DumpMemory::allocate(sizeof(dominatordata));
+
+       dom_Dominators_init(dd, basicblockcount);
+       
+       N=0;
+
+       /* 1 ist the root node of the method                    */
+       /* 0 is the artificial parent, where locals are set to their parameters */
+       dom_DFS(gd, dd, -1, 0, &N
+#ifdef DOM_DEBUG_CHECK
+                       ,basicblockcount
+#endif
+                       );
+
+       for(i = N-1; i > 0; i--) {
+               _DOM_CHECK_BOUNDS(i, 0, basicblockcount);
+               n = dd->vertex[i];
+               _DOM_CHECK_BOUNDS(n, 0, basicblockcount);
+               p = dd->parent[n];
+               s = p;
+               j = graph_get_first_predecessor(gd, n, &iter);
+               for (; j != -1; j = graph_get_next(&iter)) {
+               _DOM_CHECK_BOUNDS(j, 0, basicblockcount);
+                       if (dd->dfnum[j] <= dd->dfnum[n])
+                               s_ = j;
+                       else
+                               s_ = dd->semi[dom_AncestorWithLowestSemi(dd, j
+#ifdef DOM_DEBUG_CHECK
+                                                                                                                ,basicblockcount
+#endif
+                                                                                                                )];
+               _DOM_CHECK_BOUNDS(s_, 0, basicblockcount);
+               _DOM_CHECK_BOUNDS(s, 0, basicblockcount);
+                       if (dd->dfnum[s_] < dd->dfnum[s])
+                               s = s_;
+               }
+               dd->semi[n] = s;
+               _DOM_CHECK_BOUNDS(dd->num_bucket[s], 0, basicblockcount);
+               dd->bucket[s][dd->num_bucket[s]] = n;
+               dd->num_bucket[s]++;
+               dom_Link(dd, p, n
+#ifdef DOM_DEBUG_CHECK
+                                , basicblockcount
+#endif
+                                );
+               _DOM_CHECK_BOUNDS(p, 0, basicblockcount);
+               for(j = 0; j < dd->num_bucket[p]; j++) {
+               _DOM_CHECK_BOUNDS(j, 0, basicblockcount);
+                       v = dd->bucket[p][j];
+                       y = dom_AncestorWithLowestSemi(dd, v
+#ifdef DOM_DEBUG_CHECK
+                                                                                  , basicblockcount
+#endif
+                                                                                  );
+               _DOM_CHECK_BOUNDS(y, 0, basicblockcount);
+               _DOM_CHECK_BOUNDS(v, 0, basicblockcount);
+           if (dd->semi[y] == dd->semi[v])
+                               dd->idom[v] = p;
+                       else
+                               dd->samedom[v] = y;
+               }
+               dd->num_bucket[p] = 0;
+       }
+       for(i = 1; i < N; i++) {
+               n = dd->vertex[i];
+               _DOM_CHECK_BOUNDS(n, 0, basicblockcount);
+           if (dd->samedom[n] != -1) {
+                       _DOM_CHECK_BOUNDS(dd->samedom[n], 0, basicblockcount);
+                       dd->idom[n] = dd->idom[dd->samedom[n]];
+               }
+       }
+       return dd;
+}
+
+/********************************************
+compute Dominace Frontier
+********************************************/
+void computeDF(graphdata *gd, dominatordata *dd, int basicblockcount, int n) {
+       int c,i,j;
+       bool *_S;
+       graphiterator iter;
+
+       _S = (bool*) DumpMemory::allocate(sizeof(bool) * basicblockcount);
+       for(i = 0; i < basicblockcount; i++)
+               _S[i] = false;
+       i = graph_get_first_successor(gd, n, &iter);
+       for (; i != -1; i = graph_get_next(&iter)) {
+               _DOM_CHECK_BOUNDS(i, 0, basicblockcount);
+               if (dd->idom[i] != n)
+                       _S[i] = true;
+       }
+       for(c=0; c < basicblockcount; c++) {
+               if (dd->idom[c] == n) {
+                       computeDF(gd, dd, basicblockcount, c);
+                       for(j=0; j < dd->num_DF[c]; j++) {
+               _DOM_CHECK_BOUNDS(dd->DF[c][j], 0, basicblockcount);
+                   if (n != dd->idom[dd->DF[c][j]])
+                                       /* n does not dominate DF[c][j] -> traverse idom list? */
+                                       _S[dd->DF[c][j]] = true;
+                       }
+               }
+       }
+       for(i = 0; i < basicblockcount; i++)
+               if (_S[i]) {
+               _DOM_CHECK_BOUNDS(dd->num_DF[n], 0, basicblockcount);
+                       dd->DF[n][dd->num_DF[n]] = i;
+                       dd->num_DF[n]++;
+               }
+}
+
+
+void dom_Dominators_init(dominatordata *dd, int basicblockcount) {
+       int i;
+
+       dd->dfnum      = (int*)  DumpMemory::allocate(sizeof(int) * basicblockcount);
+       dd->vertex     = (int*)  DumpMemory::allocate(sizeof(int) * basicblockcount);
+       dd->parent     = (int*)  DumpMemory::allocate(sizeof(int) * basicblockcount);
+       dd->semi       = (int*)  DumpMemory::allocate(sizeof(int) * basicblockcount);
+       dd->ancestor   = (int*)  DumpMemory::allocate(sizeof(int) * basicblockcount);
+       dd->idom       = (int*)  DumpMemory::allocate(sizeof(int) * basicblockcount);
+       dd->samedom    = (int*)  DumpMemory::allocate(sizeof(int) * basicblockcount);
+       dd->bucket     = (int**) DumpMemory::allocate(sizeof(int*) * basicblockcount);
+       dd->num_bucket = (int*)  DumpMemory::allocate(sizeof(int) * basicblockcount);
+       dd->DF         = (int**) DumpMemory::allocate(sizeof(int*) * basicblockcount);
+       dd->num_DF     = (int*)  DumpMemory::allocate(sizeof(int) * basicblockcount);
+       dd->best       = (int*)  DumpMemory::allocate(sizeof(int) * basicblockcount);
+       for (i=0; i < basicblockcount; i++) {
+               dd->dfnum[i] = -1;
+               dd->semi[i] = dd->ancestor[i] = dd->idom[i] = dd->samedom[i] = -1;
+               dd->num_bucket[i] = 0;
+               dd->bucket[i] = (int*) DumpMemory::allocate(sizeof(int) * basicblockcount);
+               dd->num_DF[i] = 0;
+               dd->DF[i] = (int*) DumpMemory::allocate(sizeof(int) * basicblockcount);
+       }
+}
+
+/**************************************
+Create Depth First Spanning Tree
+**************************************/
+#ifdef DOM_DEBUG_CHECK
+void dom_DFS(graphdata *gd, dominatordata *dd, int p, int n, int *N,
+                        int basicblockcount) {
+#else
+void dom_DFS(graphdata *gd, dominatordata *dd, int p, int n, int *N) {
+#endif
+    int i;
+       graphiterator iter;
+
+       _DOM_CHECK_BOUNDS(n,0,basicblockcount);
+       if (dd->dfnum[n] == -1) { /* not visited till now? */
+               dd->dfnum[n] = *N;
+               _DOM_CHECK_BOUNDS(*N,0,basicblockcount);
+               dd->vertex[*N] = n;
+               dd->parent[n] = p;
+               (*N)++;
+               i = graph_get_first_successor(gd, n, &iter);
+               for (; i != -1; i = graph_get_next(&iter)) {
+                       dom_DFS(gd, dd, n, i, N
+#ifdef DOM_DEBUG_CHECK
+                                       , basicblockcount
+#endif
+                                       );
+               }
+       }
+}
+
+#ifdef DOM_DEBUG_CHECK
+int dom_AncestorWithLowestSemi(dominatordata *dd, int v, int basicblockcount) {
+#else
+int dom_AncestorWithLowestSemi(dominatordata *dd, int v) {
+#endif
+       int a,b;
+
+       _DOM_CHECK_BOUNDS(v, 0, basicblockcount);
+       a = dd->ancestor[v];
+       _DOM_CHECK_BOUNDS(a,0,basicblockcount);
+       if (dd->ancestor[a] != -1) {
+               b = dom_AncestorWithLowestSemi(dd, a
+#ifdef DOM_DEBUG_CHECK
+                                                                          , basicblockcount
+#endif
+                                                                          );
+               dd->ancestor[v] = dd->ancestor[a];
+               _DOM_CHECK_BOUNDS(b,0,basicblockcount);
+               _DOM_CHECK_BOUNDS(dd->best[v],0,basicblockcount);
+               _DOM_CHECK_BOUNDS(dd->semi[dd->best[v]],0,basicblockcount);
+               if (dd->dfnum[dd->semi[b]] < dd->dfnum[dd->semi[dd->best[v]]])
+                       dd->best[v] = b;
+       }
+       return dd->best[v];
+}
+
+#ifdef DOM_DEBUG_CHECK
+void dom_Link(dominatordata *dd, int p, int n, int basicblockcount) {
+#else
+void dom_Link(dominatordata *dd, int p, int n) {
+#endif
+       _DOM_CHECK_BOUNDS(n,0,basicblockcount);
+       dd->ancestor[n] = p;
+       dd->best[n] = n;
+}
+
+/*********************************************************/
+
+typedef struct basicblock_info basicblock_info;
+
+struct basicblock_info {
+       basicblock *bb;
+       int dfnum;
+       basicblock_info *parent;
+       basicblock_info *semi;
+       basicblock_info *ancestor;
+       basicblock_info *best;
+       basicblock_info *idom;
+       basicblock_info *samedom;
+       basicblock_info **bucket;
+       unsigned bucketcount;
+};
+
+typedef struct dominator_tree_info dominator_tree_info;
+
+struct dominator_tree_info {
+       jitdata *jd;
+       basicblock_info *basicblocks;
+       basicblock_info **df_map;
+       unsigned df_counter;
+};
+
+static dominator_tree_info *dominator_tree_init(jitdata *jd) {
+       dominator_tree_info *di;
+       basicblock *itb;
+       basicblock_info *iti;
+
+       di = (dominator_tree_info*) DumpMemory::allocate(sizeof(dominator_tree_info));
+
+       di->jd = jd;
+
+       di->basicblocks = (basicblock_info*) DumpMemory::allocate(sizeof(basicblock_info) * jd->basicblockcount);
+       MZERO(di->basicblocks, basicblock_info, jd->basicblockcount);
+       
+       for (iti = di->basicblocks; iti != di->basicblocks + jd->basicblockcount; ++iti) {
+               iti->dfnum = -1;
+               iti->bucket = (basicblock_info**) DumpMemory::allocate(sizeof(basicblock_info*) * jd->basicblockcount);
+               iti->bucketcount = 0;
+       }
+
+       for (itb = jd->basicblocks; itb; itb = itb->next) {
+               di->basicblocks[itb->nr].bb = itb;
+       }
+
+       di->df_map = (basicblock_info**) DumpMemory::allocate(sizeof(basicblock_info*) * jd->basicblockcount);
+       MZERO(di->df_map, basicblock_info *, jd->basicblockcount);
+
+       di->df_counter = 0;
+
+       return di;
+}
+
+static inline basicblock_info *dominator_tree_get_basicblock(dominator_tree_info *di, basicblock *bb) {
+       return di->basicblocks + bb->nr;
+}
+
+static void dominator_tree_depth_first_search(
+       dominator_tree_info *di, basicblock_info *parent, basicblock_info *node
+) {
+       basicblock **it;
+
+       if (node->dfnum == -1) {
+
+               node->dfnum = di->df_counter;
+               node->parent = parent;
+               di->df_map[di->df_counter] = node;
+               di->df_counter += 1;
+
+               for (it = node->bb->successors; it != node->bb->successors + node->bb->successorcount; ++it) {
+                       dominator_tree_depth_first_search(
+                               di, node, 
+                               dominator_tree_get_basicblock(di, *it)
+                       );
+               }
+       }
+}
+
+void dominator_tree_link(dominator_tree_info *di, basicblock_info *parent, basicblock_info *node) {
+       node->ancestor = parent;
+       node->best = node;
+}
+
+basicblock_info *dominator_tree_ancestor_with_lowest_semi(
+       dominator_tree_info *di, basicblock_info *node
+) {
+       basicblock_info *a, *b;
+
+       a = node->ancestor;
+
+       if (a->ancestor != NULL) {
+               b = dominator_tree_ancestor_with_lowest_semi(di, a);
+               node->ancestor = a->ancestor;
+               if (b->semi->dfnum < node->best->semi->dfnum) {
+                       node->best = b;
+               }
+       }
+
+       return node->best;
+}
+
+void dominator_tree_build_intern(jitdata *jd) {
+       
+       dominator_tree_info *di;
+       basicblock_info *node;
+       basicblock_info *semicand;
+       basicblock_info *pred;
+       basicblock **itb;
+       basicblock_info **itii;
+       basicblock_info *v, *y;
+       int i;
+
+       di = dominator_tree_init(jd);
+
+       dominator_tree_depth_first_search(di, NULL, dominator_tree_get_basicblock(di, jd->basicblocks));
+
+       for (i = di->df_counter - 1; i >= 1; --i) {
+               node = di->df_map[i];
+
+               node->semi = node->parent;
+
+               for (
+                       itb = node->bb->predecessors; 
+                       itb != node->bb->predecessors + node->bb->predecessorcount; 
+                       ++itb
+               ) {
+
+                       pred = dominator_tree_get_basicblock(di, *itb);
+
+                       if (pred->dfnum <= node->dfnum) {
+                               semicand = pred;
+                       } else {
+                               semicand = dominator_tree_ancestor_with_lowest_semi(di, pred)->semi;
+                       }
+
+                       if (semicand->dfnum < node->semi->dfnum) {
+                               node->semi = semicand;
+                       }
+               }
+
+               node->semi->bucket[node->semi->bucketcount] = node;
+               node->semi->bucketcount += 1;
+
+               dominator_tree_link(di, node->parent, node);
+
+               for (itii = node->parent->bucket; itii != node->parent->bucket + node->parent->bucketcount; ++itii) {
+                       v = *itii;
+                       y = dominator_tree_ancestor_with_lowest_semi(di, v);
+                       if (y->semi == v->semi) {
+                               v->idom = node->parent;
+                       } else {
+                               v->samedom = y;
+                       }
+               }
+
+               node->parent->bucketcount = 0;
+       }
+
+       for (i = 1; i < di->df_counter; ++i) {
+               node = di->df_map[i];
+               if (node->samedom) {
+                       node->idom = node->samedom->idom;
+               }
+
+               node->bb->idom = node->idom->bb;
+               node->idom->bb->domsuccessorcount += 1;
+       }
+}
+
+void dominator_tree_link_children(jitdata *jd) {
+       basicblock *bb;
+       /* basicblock number => current number of successors */
+       unsigned *numsuccessors;
+
+       // Create new dump memory area.
+       DumpMemoryArea dma;
+
+       /* Allocate memory for successors */
+
+       for (bb = jd->basicblocks; bb; bb = bb->next) {
+               if (bb->domsuccessorcount > 0) {
+                       bb->domsuccessors = (basicblock**) DumpMemory::allocate(sizeof(basicblock*) * bb->domsuccessorcount);
+               }
+       }
+
+       /* Allocate memory for per basic block counter of successors */
+
+       numsuccessors = (unsigned*) DumpMemory::allocate(sizeof(unsigned) * jd->basicblockcount);
+       MZERO(numsuccessors, unsigned, jd->basicblockcount);
+
+       /* Link immediate dominators with successors */
+
+       for (bb = jd->basicblocks; bb; bb = bb->next) {
+               if (bb->idom) {
+                       bb->idom->domsuccessors[numsuccessors[bb->idom->nr]] = bb;
+                       numsuccessors[bb->idom->nr] += 1;
+               }
+       }
+}
+
+bool dominator_tree_build(jitdata *jd) {
+       // Create new dump memory area.
+       DumpMemoryArea dma;
+
+       dominator_tree_build_intern(jd);
+
+       dominator_tree_link_children(jd);
+
+       return true;
+}
+
+typedef struct dominance_frontier_item dominance_frontier_item;
+
+struct dominance_frontier_item {
+       basicblock *bb;
+       dominance_frontier_item *next;
+};
+
+typedef struct dominance_frontier_list dominance_frontier_list;
+
+struct dominance_frontier_list {
+       dominance_frontier_item *first;
+       unsigned count;
+};
+
+void dominance_frontier_list_add(dominance_frontier_list *list, basicblock *bb) {
+       dominance_frontier_item *item;
+       
+       for (item = list->first; item; item = item->next) {
+               if (item->bb == bb) return;
+       }
+
+       item = (dominance_frontier_item*) DumpMemory::allocate(sizeof(dominance_frontier_item));
+       item->bb = bb;
+       item->next = list->first;
+       list->first = item;
+       list->count += 1;
+}
+
+typedef struct dominance_frontier_info dominance_frontier_info;
+
+struct dominance_frontier_info {
+       jitdata *jd;
+       dominance_frontier_list *map;
+};
+
+dominance_frontier_info *dominance_frontier_init(jitdata *jd) {
+       dominance_frontier_info *dfi = (dominance_frontier_info*) DumpMemory::allocate(sizeof(dominance_frontier_info));
+
+       dfi->jd = jd;
+
+       dfi->map = (dominance_frontier_list*) DumpMemory::allocate(sizeof(dominance_frontier_list) * jd->basicblockcount);
+       MZERO(dfi->map, dominance_frontier_list, jd->basicblockcount);
+
+       return dfi;
+}
+
+bool dominance_frontier_dominates(basicblock *d, basicblock *x) {
+       x = x->idom;
+
+       while (x != NULL) {
+               if (x == d) {
+                       return true;
+               }
+               x = x->idom;
+       }
+
+       return false;
+}
+
+void dominance_frontier_for_block(dominance_frontier_info *dfi, basicblock *b) {
+       basicblock **it;
+       dominance_frontier_item *itdf;
+       dominance_frontier_list s = { NULL, 0 };
+
+       for (it = b->successors; it != b->successors + b->successorcount; ++it) {
+               if ((*it)->idom != b) {
+                       dominance_frontier_list_add(&s, *it);
+               }
+       }
+
+       for (it = b->domsuccessors; it != b->domsuccessors + b->domsuccessorcount; ++it) {
+               dominance_frontier_for_block(dfi, *it);
+               for (itdf = dfi->map[(*it)->nr].first; itdf; itdf = itdf->next) {
+                       if (! dominance_frontier_dominates(b, itdf->bb)) {
+                               dominance_frontier_list_add(&s, itdf->bb);
+                       }
+               }
+       }
+
+       dfi->map[b->nr] = s;
+}
+
+void dominance_frontier_store(dominance_frontier_info *dfi) {
+       basicblock *bb;
+       dominance_frontier_item *itdf;
+       basicblock **itout;
+
+       for (bb = dfi->jd->basicblocks; bb; bb = bb->next) {
+               if (bb->nr < dfi->jd->basicblockcount) {
+                       if (dfi->map[bb->nr].count > 0) {
+                               bb->domfrontiercount = dfi->map[bb->nr].count;
+                               itout = bb->domfrontier = (basicblock**) DumpMemory::allocate(sizeof(basicblock*) * bb->domfrontiercount);
+                               for (itdf = dfi->map[bb->nr].first; itdf; itdf = itdf->next) {
+                                       *itout = itdf->bb;
+                                       itout += 1;
+                               }
+                       }
+               }
+       }
+}
+
+bool dominance_frontier_build(jitdata *jd) {
+       // Create new dump memory area.
+       DumpMemoryArea dma;
+
+       dominance_frontier_info *dfi = dominance_frontier_init(jd);
+       dominance_frontier_for_block(dfi, jd->basicblocks);
+       dominance_frontier_store(dfi);
+}
+
+#include "vm/jit/show.hpp"
+#include "vm/jit/python.h"
+
+extern "C" void graph_add_edge( graphdata *gd, int from, int to );
+
+void dominator_tree_validate(jitdata *jd, dominatordata *_dd) {
+       graphdata *gd;
+       int i, j;
+       basicblock *bptr, **it;
+       dominatordata *dd;
+       int *itnr;
+       bool found;
+
+       // Create new dump memory area.
+       DumpMemoryArea dma;
+
+       fprintf(stderr, "%s/%s: \n", jd->m->clazz->name->text, jd->m->name->text);
+       gd = graph_init(jd->basicblockcount);
+
+       for (bptr = jd->basicblocks; bptr; bptr = bptr->next) {
+               for (it = bptr->successors; it != bptr->successors + bptr->successorcount; ++it) {
+                       graph_add_edge(gd, bptr->nr, (*it)->nr);
+               }
+       }
+
+       dd = compute_Dominators(gd, jd->basicblockcount);
+
+       for (bptr = jd->basicblocks; bptr; bptr = bptr->next) {
+               if (bptr->flags >= BBREACHED) {
+                       if (bptr->idom == NULL) {
+                               if (!(dd->idom[bptr->nr] == -1)) {
+                                       printf("-- %d %d\n", dd->idom[bptr->nr], bptr->nr);
+                                       assert(0);
+                               }
+                       } else {
+                               assert(dd->idom[bptr->nr] == bptr->idom->nr);
+                       }
+               }
+       }
+
+       computeDF(gd, dd, jd->basicblockcount, 0);
+
+       for (bptr = jd->basicblocks; bptr; bptr = bptr->next) {
+               if (bptr->flags >= BBREACHED) {
+                       assert(bptr->domfrontiercount == dd->num_DF[bptr->nr]);
+                       for (itnr = dd->DF[bptr->nr]; itnr != dd->DF[bptr->nr] + dd->num_DF[bptr->nr]; ++itnr) {
+                               found = false;
+                               for (it = bptr->domfrontier; it != bptr->domfrontier + bptr->domfrontiercount; ++it) {
+                                       if ((*it)->nr == *itnr) {
+                                               found =true; break;
+                                       }
+                               }
+                               assert(found);
+                       }
+               }
+       }
+}
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
diff --git a/src/vm/jit/optimizing/dominators.h b/src/vm/jit/optimizing/dominators.h
deleted file mode 100644 (file)
index 376b78e..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-/* src/vm/jit/optimizing/dominators.h - Dominators and Dominance Frontier header
-
-   Copyright (C) 2005, 2006 R. Grafl, A. Krall, C. Kruegel, C. Oates,
-   R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
-   C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
-   Institut f. Computersprachen - TU Wien
-
-   This file is part of CACAO.
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2, or (at
-   your option) any later version.
-
-   This program is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-   02111-1307, USA.
-
-   Contact: cacao@complang.tuwien.ac.at
-
-   Authors: Christian Ullrich
-
-
-*/
-
-
-#ifndef _DOMINATORS_H
-#define _DOMINATORS_H
-
-#include "vm/jit/optimizing/graph.h"
-
-#if !defined(NDEBUG)
-# include <assert.h>
-/* # define DOM_DEBUG_CHECK */
-# define DOM_DEBUG_VERBOSE
-#endif
-
-#ifdef DOM_DEBUG_CHECK
-# define _DOM_CHECK_BOUNDS(i,l,h) assert( ((i) >= (l)) && ((i) < (h)));
-# define _DOM_ASSERT(a) assert((a));
-#else
-# define _DOM_CHECK_BOUNDS(i,l,h)
-# define _DOM_ASSERT(a)
-#endif
-
-struct dominatordata {
-       int *dfnum;           /* [0..ls->basicblockcount[ */
-       int *vertex;          /* [0..ls->basicblockcount[ */
-       int *parent;          /* [0..ls->basicblockcount[ */
-       int *semi;            /* [0..ls->basicblockcount[ */
-       int *ancestor;        /* [0..ls->basicblockcount[ */
-       int *idom;            /* [0..ls->basicblockcount[ */
-       int *samedom;         /* [0..ls->basicblockcount[ */
-       int **bucket;         /* [0..ls->basicblockcount[[0..ls->bbc[ */
-       int *num_bucket;      /* [0..ls->basicblockcount[ */
-       int *best;            /* [0..ls->basicblockcount[ */
-       int **DF;             /* [0..ls->basicblockcount[[0..ls->bbc[ */
-       int *num_DF;          /* [0..ls->basicblockcount[ */
-};     
-
-typedef struct dominatordata dominatordata;
-
-/* function prototypes */
-dominatordata *compute_Dominators(graphdata *gd, int basicblockcount);
-void computeDF(graphdata *gd, dominatordata *dd, int basicblockcount, int n);
-
-/* ............................... */
-
-bool dominator_tree_build(jitdata *jd);
-
-bool dominance_frontier_build(jitdata *jd);
-
-void dominator_tree_validate(jitdata *jd, dominatordata *dd);
-
-#endif /* _DOMINATORS_H */
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- */
diff --git a/src/vm/jit/optimizing/dominators.hpp b/src/vm/jit/optimizing/dominators.hpp
new file mode 100644 (file)
index 0000000..bd7df65
--- /dev/null
@@ -0,0 +1,99 @@
+/* src/vm/jit/optimizing/dominators.hpp - Dominators and Dominance Frontier header
+
+   Copyright (C) 2005, 2006, 2008
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+   This file is part of CACAO.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.
+
+*/
+
+
+#ifndef _DOMINATORS_HPP
+#define _DOMINATORS_HPP
+
+#include "config.h"
+
+#include "vm/jit/optimizing/graph.h"
+
+#if !defined(NDEBUG)
+# include <assert.h>
+/* # define DOM_DEBUG_CHECK */
+# define DOM_DEBUG_VERBOSE
+#endif
+
+#ifdef DOM_DEBUG_CHECK
+# define _DOM_CHECK_BOUNDS(i,l,h) assert( ((i) >= (l)) && ((i) < (h)));
+# define _DOM_ASSERT(a) assert((a));
+#else
+# define _DOM_CHECK_BOUNDS(i,l,h)
+# define _DOM_ASSERT(a)
+#endif
+
+struct dominatordata {
+       int *dfnum;           /* [0..ls->basicblockcount[ */
+       int *vertex;          /* [0..ls->basicblockcount[ */
+       int *parent;          /* [0..ls->basicblockcount[ */
+       int *semi;            /* [0..ls->basicblockcount[ */
+       int *ancestor;        /* [0..ls->basicblockcount[ */
+       int *idom;            /* [0..ls->basicblockcount[ */
+       int *samedom;         /* [0..ls->basicblockcount[ */
+       int **bucket;         /* [0..ls->basicblockcount[[0..ls->bbc[ */
+       int *num_bucket;      /* [0..ls->basicblockcount[ */
+       int *best;            /* [0..ls->basicblockcount[ */
+       int **DF;             /* [0..ls->basicblockcount[[0..ls->bbc[ */
+       int *num_DF;          /* [0..ls->basicblockcount[ */
+};     
+
+typedef struct dominatordata dominatordata;
+
+/* function prototypes */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+dominatordata *compute_Dominators(graphdata *gd, int basicblockcount);
+void computeDF(graphdata *gd, dominatordata *dd, int basicblockcount, int n);
+
+/* ............................... */
+
+bool dominator_tree_build(jitdata *jd);
+
+bool dominance_frontier_build(jitdata *jd);
+
+void dominator_tree_validate(jitdata *jd, dominatordata *dd);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _DOMINATORS_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:
+ */
index cca121315a344b1328a5d83dbce6e3abf5f2522c..b0565836fd03817f3fdd74f6779a9e5deb8d9123 100644 (file)
@@ -28,7 +28,7 @@
 #include "vm/class.h"
 #include "vm/classcache.h"
 
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
 #include "vm/jit/optimizing/escape.h"
 
 #include <stdarg.h>
index bb7cf7bb34081930a20d5a18b10c35dc9be4bf95..4b9b9ec4e1097bc100e84650f24e5814c8f8bc2b 100644 (file)
@@ -24,7 +24,7 @@
 #ifndef _VM_JIT_OPTIMIZING_ESCAPE_H
 #define _VM_JIT_OPTIMIZING_ESCAPE_H
 
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
 #include "vm/method.h"
 
 typedef enum {
index 99af008421ebd61726cc3b3622e014f402269289..fdde38c0c9fa9ff75a0b245758ccaf3f9e69cce7 100644 (file)
@@ -30,7 +30,7 @@
 
 #include "toolbox/bitvector.h"
 
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
 
 #include "vm/jit/optimizing/lsra.h"
 #include "vm/jit/optimizing/ssa.h"
index 12ad79381d988df044227004e16566caa8a6bf1c..088eb45683f815abdb4ff07e9059b778970df629 100644 (file)
@@ -1,9 +1,7 @@
 /* src/vm/jit/optimizing/graph.h - control flow graph header
 
-   Copyright (C) 2005, 2006 R. Grafl, A. Krall, C. Kruegel, C. Oates,
-   R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
-   C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
-   Institut f. Computersprachen - TU Wien
+   Copyright (C) 2005, 2006, 2008
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
 
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
    02111-1307, USA.
 
-   Contact: cacao@complang.tuwien.ac.at
-
-   Authors: Christian Ullrich
-
-
 */
 
 
 #ifndef _LSRA_GRAPH_H
 #define _LSRA_GRAPH_H
 
+#include "config.h"
+
 #include "vm/jit/optimizing/lsra.h"
 
 #if !defined(NDEBUG)
@@ -77,6 +72,11 @@ typedef struct graph_element graph_element;
 typedef graph_element *graphiterator;
 
 /* function prototypes */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 void transform_BB(jitdata *, graphdata *gd);
 graphdata *graph_init(int basicblockcount);
                                             /* Generate the CFG */
@@ -90,6 +90,9 @@ int graph_get_num_successor(graphdata *gd, int b_index);
 bool graph_has_multiple_successors( graphdata *gd, int b_index);
 bool graph_has_multiple_predecessors( graphdata *gd, int b_index);
 
+#ifdef __cplusplus
+}
+#endif
 
 #endif /* _LSRA_GRAPH_H */
 
index 2decc95532b2ca74cef8801230a06ef1b1480083..c463d1e2f1cef05bb70a93b9da0570ca75182934 100644 (file)
 #include "vm/method.h"
 #include "vm/vm.hpp"
 
-#include "vm/jit/codegen-common.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/codegen-common.hpp"
+#include "vm/jit/jit.hpp"
 #include "vm/jit/reg.h"
-#include "vm/jit/show.h"
+#include "vm/jit/show.hpp"
 
 
 /* patterns for a total number of 3 instructions ******************************/
index f10ced797fbf7b59ad0531288a18b9ef4702a5fa..92c32f6c4dff5396af37e4213a1002f72903ec25 100644 (file)
 #define _IFCONV_H
 
 #include "config.h"
-#include "vm/types.h"
 
-#include "vm/jit/codegen-common.h"
-#include "vm/jit/jit.h"
-#include "vm/jit/reg.h"
+#include <stdbool.h>
+
+#include "vm/jit/jit.hpp"
 
 
 /* function prototypes ********************************************************/
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 bool ifconv_static(jitdata *jd);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* _IFCONV_H */
 
 
index c7fdb8d4d7495561b8f62364c2bf5e9f90b89d08..d8f8d349f85cc7d84e88595ead45fd68317b95a9 100644 (file)
 #include "toolbox/bitvector.h"
 #include "toolbox/worklist.h"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/resolve.h"
 #include "vm/exceptions.hpp"
 #include "vm/string.hpp"
 
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
 
 #include "vm/jit/optimizing/graph.h"
 #include "vm/jit/optimizing/lsra.h"
index 08f4ae6ca6489ed2c50f6efe76d82d5e59f29b60..94655cf97ae2a35e1548a27a13687f9262bcf459 100644 (file)
@@ -26,7 +26,9 @@
 #ifndef _LIFETIMES_H
 #define _LIFETIMES_H
 
-#include "vm/jit/optimizing/dominators.h"
+#include "config.h"
+
+#include "vm/jit/optimizing/dominators.hpp"
 
 #if !defined(NDEBUG)
 # include <assert.h>
index b5a1b62bae86d153dc6c837191b81e1dea7a22ea..e5e571ef30c237398dfb054c0eb18f74caa59a35 100644 (file)
@@ -41,7 +41,7 @@
 
 #include "vm/jit/abi.h"
 #include "vm/jit/reg.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
 
 #include "vm/jit/optimizing/graph.h"
 #include "vm/jit/optimizing/lifetimes.h"
@@ -538,9 +538,6 @@ void lsra_alloc(jitdata *jd, int *lifet, int lifetimecount, int *mem_use)
        struct lifetime *lt;
        struct freemem *fmem;
        int lt_index;
-#ifdef HAS_4BYTE_STACKSLOT
-       struct freemem *fmem_2;
-#endif
        methodinfo *m;
        registerdata *rd;
        lsradata *ls;
@@ -552,11 +549,6 @@ void lsra_alloc(jitdata *jd, int *lifet, int lifetimecount, int *mem_use)
        fmem=DNEW(struct freemem);
        fmem->off=-1;
        fmem->next=NULL;
-#ifdef HAS_4BYTE_STACKSLOT
-       fmem_2=DNEW(struct freemem);
-       fmem_2->off=-1;
-       fmem_2->next=NULL;
-#endif
 
        for (lt_index = 0; lt_index < lifetimecount; lt_index ++) {
                lt = ls->lifetime + lifet[lt_index];
@@ -565,11 +557,6 @@ void lsra_alloc(jitdata *jd, int *lifet, int lifetimecount, int *mem_use)
 #endif
                if (lt->regoff == -1) {
                        flags = INMEMORY;
-#ifdef HAS_4BYTE_STACKSLOT
-                       if (IS_2_WORD_TYPE(lt->type))
-                               regoff = lsra_getmem(lt, fmem_2, mem_use);
-                       else
-#endif
                        regoff = lsra_getmem(lt, fmem, mem_use);
                } else {
                        flags = lt->savedvar;
@@ -589,17 +576,7 @@ int lsra_getmem(struct lifetime *lt, struct freemem *fmem, int *mem_use)
        /* no memmory allocated till now, or all other are still live */
        if ((fmem->next == NULL) || (fmem->next->end > lt->i_start)) {
 /*     if (1) { */
-#ifdef HAS_4BYTE_STACKSLOT
-               if (IS_2_WORD_TYPE(lt->type))
-                       if ( (*mem_use)&1 ) /* align memory location for 2 Word Types */
-                               (*mem_use)++;
                fm=lsra_getnewmem(mem_use);
-               if (IS_2_WORD_TYPE(lt->type))
-                       /* allocate a second following Slot for 2 Word Types */
-                       (*mem_use)++;
-#else
-               fm=lsra_getnewmem(mem_use);
-#endif
        } else {
                /* Speicherstelle frei */
                fm=fmem->next;
@@ -934,7 +911,7 @@ void lsra_calc_lifetime_length(jitdata *jd)
 
                        switch (lt->type) {
                        case TYPE_LNG:
-#if (defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)) || defined (__I386__)
+#if defined (__I386__)
                                flags = 0;
 #else
                                flags = 1;
index 35ad152d909a28132a53ec65df1765c4acf330f0..aad9f09c49ed59a5fe9dca823df621163e4fedac 100644 (file)
 
 #include "mm/memory.h"
 
-#include "threads/threadlist.h"
+#include "threads/threadlist.hpp"
 #include "threads/thread.hpp"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #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/jit.hpp"
 #include "vm/jit/methodheader.h"
 #include "vm/jit/methodtree.h"
 
-#include "vm/jit/optimizing/recompile.h"
+#include "vm/jit/optimizing/recompiler.hpp"
 
 
 /* profile_init ****************************************************************
@@ -92,13 +92,12 @@ static void profile_thread(void)
                threads_sleep(0, nanos);
                runs++;
 
-               /* lock the threads lists */
-
-               threadlist_lock();
+               // Lock the thread lists.
+               ThreadList_lock();
 
                /* iterate over all started threads */
 
-               for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
+               for (t = ThreadList_first(); t != NULL; t = ThreadList_next(t)) {
                        /* is this a Java thread? */
 
                        if (!(t->flags & THREAD_FLAG_JAVA))
@@ -148,16 +147,15 @@ static void profile_thread(void)
                                                        /* add this method to the method list and
                                                           start recompilation */
 
-                                                       recompile_queue_method(m);
+                                                       Recompiler_queue_method(m);
                                                }
                                        }
                                }
                        }
                }
 
-               /* unlock the threads lists */
-
-               threadlist_unlock();
+               // Unlock the thread lists.
+               ThreadList_unlock();
        }
 }
 #endif
@@ -195,9 +193,6 @@ bool profile_start_thread(void)
 #if !defined(NDEBUG)
 void profile_printstats(void)
 {
-       list_t                 *l;
-       list_method_entry      *lme;
-       list_method_entry      *tlme;
        classinfo              *c;
        methodinfo             *m;
        codeinfo               *code;
@@ -213,8 +208,8 @@ void profile_printstats(void)
        cycles    = 0;
 
        /* create new method list */
-
-       l = list_create(OFFSET(list_method_entry, linkage));
+       // TODO Use a sorted container.
+       List* l = List_new();
 
        /* iterate through all classes and methods */
 
@@ -245,15 +240,10 @@ void profile_printstats(void)
                                                frequency += code->frequency;
                                                cycles    += code->cycles;
 
-                                               /* create new list entry */
-
-                                               lme = NEW(list_method_entry);
-                                               lme->m = m;
-
                                                /* sort the new entry into the list */
                                                
-                                               if ((tlme = list_first(l)) == NULL) {
-                                                       list_add_first(l, lme);
+                                               if (List_empty(l) == NULL) {
+                                                       List_push_back(l, m);
                                                }
                                                else {
                                                        for (; tlme != NULL; tlme = list_next(l, tlme)) {
diff --git a/src/vm/jit/optimizing/recompile.c b/src/vm/jit/optimizing/recompile.c
deleted file mode 100644 (file)
index 3b302d8..0000000
+++ /dev/null
@@ -1,271 +0,0 @@
-/* src/vm/jit/optimizing/recompile.c - recompilation system
-
-   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 "mm/memory.h"
-
-#include "threads/lock-common.h"
-#include "threads/thread.hpp"
-
-#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/jit.h"
-
-#include "vm/jit/optimizing/recompile.h"
-
-
-/* global variables ***********************************************************/
-
-static java_object_t *lock_thread_recompile;
-static list_t        *list_recompile_methods;
-
-
-/* recompile_init **************************************************************
-
-   Initializes the recompilation system.
-
-*******************************************************************************/
-
-bool recompile_init(void)
-{
-       TRACESUBSYSTEMINITIALIZATION("recompile_init");
-
-       /* initialize the recompile lock object */
-
-       lock_thread_recompile = NEW(java_object_t);
-
-       LOCK_INIT_OBJECT_LOCK(lock_thread_recompile);
-
-       /* create method list */
-
-       list_recompile_methods = list_create(OFFSET(list_method_entry, linkage));
-
-       /* everything's ok */
-
-       return true;
-}
-
-
-/* recompile_replace_vftbl *****************************************************
-
-   XXX
-
-*******************************************************************************/
-
-static void recompile_replace_vftbl(methodinfo *m)
-{
-       codeinfo               *code;
-       codeinfo               *pcode;
-       u4                      slot;
-       classcache_name_entry  *nmen;
-       classcache_class_entry *clsen;
-       classinfo              *c;
-       vftbl_t                *vftbl;
-       s4                      i;
-
-       /* get current and previous codeinfo structure */
-
-       code  = m->code;
-       pcode = code->prev;
-
-       assert(pcode);
-
-       /* iterate over all classes */
-
-       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;
-
-                               if (c == NULL)
-                                       continue;
-
-                               /* Search for entrypoint of the previous codeinfo in
-                                  the vftbl and replace it with the current one. */
-
-                               vftbl = c->vftbl;
-
-                               /* Is the class linked? Means, is the vftbl finished? */
-
-                               if (!(c->state & CLASS_LINKED))
-                                       continue;
-
-                               /* Does the class have a vftbl? Some internal classes
-                                  (e.g. $NEW$) are linked, but do not have a
-                                  vftbl. */
-
-                               if (vftbl == NULL)
-                                       continue;
-
-                               for (i = 0; i < vftbl->vftbllength; i++) {
-                                       if (vftbl->table[i] == pcode->entrypoint) {
-#if !defined(NDEBUG)
-                                               printf("replacing vftbl in: ");
-                                               class_println(c);
-#endif
-                                               vftbl->table[i] = code->entrypoint;
-                                       }
-                               }
-                       }
-               }
-       }
-}
-
-
-/* recompile_thread ************************************************************
-
-   XXX
-
-*******************************************************************************/
-
-static void recompile_thread(void)
-{
-       list_method_entry *lme;
-
-       while (true) {
-               /* get the lock on the recompile lock object, so we can call wait */
-
-               LOCK_MONITOR_ENTER(lock_thread_recompile);
-
-               /* wait forever on that object till we are signaled */
-       
-               LOCK_WAIT_FOREVER(lock_thread_recompile);
-
-               /* leave the lock */
-
-               LOCK_MONITOR_EXIT(lock_thread_recompile);
-
-               /* get the next method and recompile it */
-
-               while ((lme = list_first(list_recompile_methods)) != NULL) {
-                       /* recompile this method */
-
-                       if (jit_recompile(lme->m) != NULL) {
-                               /* replace in vftbl's */
-
-                               recompile_replace_vftbl(lme->m);
-                       }
-                       else {
-                               /* XXX what is the right-thing(tm) to do here? */
-
-                               exceptions_print_current_exception();
-                       }
-
-                       /* remove the compiled method */
-
-                       list_remove(list_recompile_methods, lme);
-
-                       /* free the entry */
-
-                       FREE(lme, list_method_entry);
-               }
-       }
-}
-
-
-/* recompile_start_thread ******************************************************
-
-   Starts the recompilation thread.
-
-*******************************************************************************/
-
-bool recompile_start_thread(void)
-{
-       utf *name;
-
-       name = utf_new_char("Recompiler");
-
-       if (!threads_thread_start_internal(name, recompile_thread))
-               return false;
-
-       /* everything's ok */
-
-       return true;
-}
-
-
-/* recompile_queue_method ******************************************************
-
-   Adds a method to the recompilation list and signal the
-   recompilation thread that there is some work to do.
-
-*******************************************************************************/
-
-void recompile_queue_method(methodinfo *m)
-{
-       list_method_entry *lme;
-
-       /* create a method entry */
-
-       lme = NEW(list_method_entry);
-       lme->m = m;
-
-       /* and add it to the list */
-
-       list_add_last(list_recompile_methods, lme);
-
-       /* get the lock on the recompile lock object, so we can call notify */
-
-       LOCK_MONITOR_ENTER(lock_thread_recompile);
-
-       /* signal the recompiler thread */
-       
-       LOCK_NOTIFY(lock_thread_recompile);
-
-       /* leave the lock */
-
-       LOCK_MONITOR_EXIT(lock_thread_recompile);
-}
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- */
diff --git a/src/vm/jit/optimizing/recompile.h b/src/vm/jit/optimizing/recompile.h
deleted file mode 100644 (file)
index 42e53a6..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-/* src/vm/jit/optimizing/recompile.h - recompilation system
-
-   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 _RECOMPILE_H
-#define _RECOMPILE_H
-
-#include "config.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "vm/types.h"
-
-#include "vm/global.h"
-
-
-/* list_method_entry **********************************************************/
-
-typedef struct list_method_entry list_method_entry;
-
-struct list_method_entry {
-       methodinfo *m;
-       listnode_t  linkage;
-};
-
-
-/* function prototypes ********************************************************/
-
-bool recompile_init(void);
-bool recompile_start_thread(void);
-
-void recompile_queue_method(methodinfo *m);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _RECOMPILE_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:
- */
diff --git a/src/vm/jit/optimizing/recompiler.cpp b/src/vm/jit/optimizing/recompiler.cpp
new file mode 100644 (file)
index 0000000..8cd46d4
--- /dev/null
@@ -0,0 +1,236 @@
+/* src/vm/jit/optimizing/recompiler.cpp - recompilation system
+
+   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 "mm/memory.h"
+
+#include "threads/condition.hpp"
+#include "threads/mutex.hpp"
+#include "threads/thread.hpp"
+
+#include "vm/classcache.h"
+#include "vm/exceptions.hpp"
+#include "vm/options.h"
+#include "vm/string.hpp"
+
+#include "vm/jit/builtin.hpp"
+#include "vm/jit/code.hpp"
+#include "vm/jit/jit.hpp"
+
+#include "vm/jit/optimizing/recompiler.hpp"
+
+
+/**
+ * Stop the worker thread.
+ */
+Recompiler::~Recompiler()
+{
+       // Set the running flag to false.
+       _run = false;
+
+       // Now signal the worker thread.
+       _cond.signal();
+
+       // TODO We should wait here until the thread exits.
+}
+
+
+/* recompile_replace_vftbl *****************************************************
+
+   XXX
+
+*******************************************************************************/
+
+static void recompile_replace_vftbl(methodinfo *m)
+{
+       codeinfo               *code;
+       codeinfo               *pcode;
+       u4                      slot;
+       classcache_name_entry  *nmen;
+       classcache_class_entry *clsen;
+       classinfo              *c;
+       vftbl_t                *vftbl;
+       s4                      i;
+
+       /* get current and previous codeinfo structure */
+
+       code  = m->code;
+       pcode = code->prev;
+
+       assert(pcode);
+
+       /* iterate over all classes */
+
+       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;
+
+                               if (c == NULL)
+                                       continue;
+
+                               /* Search for entrypoint of the previous codeinfo in
+                                  the vftbl and replace it with the current one. */
+
+                               vftbl = c->vftbl;
+
+                               /* Is the class linked? Means, is the vftbl finished? */
+
+                               if (!(c->state & CLASS_LINKED))
+                                       continue;
+
+                               /* Does the class have a vftbl? Some internal classes
+                                  (e.g. $NEW$) are linked, but do not have a
+                                  vftbl. */
+
+                               if (vftbl == NULL)
+                                       continue;
+
+                               for (i = 0; i < vftbl->vftbllength; i++) {
+                                       if (vftbl->table[i] == pcode->entrypoint) {
+#if !defined(NDEBUG)
+                                               printf("replacing vftbl in: ");
+                                               class_println(c);
+#endif
+                                               vftbl->table[i] = code->entrypoint;
+                                       }
+                               }
+                       }
+               }
+       }
+}
+
+
+/**
+ * The actual recompilation thread.
+ */
+void Recompiler::thread()
+{
+       // FIXME This just works for one recompiler.
+       Recompiler& r = VM::get_current()->get_recompiler();
+
+       while (r._run == true) {
+               // Enter the recompile mutex, so we can call wait.
+               r._mutex.lock();
+
+               // Wait forever on that condition until we are signaled.
+               r._cond.wait(r._mutex);
+
+               // Leave the mutex.
+               r._mutex.unlock();
+
+               // FIXME Move this into the for loop.
+               if (r._run == false)
+                       break;
+
+               // Sanity check.
+               assert(r._methods.empty() == false);
+
+               // Get the next method form the queue and recompile it.
+               while (r._methods.empty() == false) {
+                       methodinfo* m = r._methods.front();
+
+                       // Recompile this method.
+                       if (jit_recompile(m) != NULL) {
+                               // Replace in vftbl's.
+                               recompile_replace_vftbl(m);
+                       }
+                       else {
+                               // XXX What is the right-thing(tm) to do here?
+                               exceptions_print_current_exception();
+                       }
+
+                       // Remove the method from the queue.
+                       r._methods.pop();
+               }
+       }
+}
+
+
+/**
+ * Start the recompilation thread.
+ *
+ * @return true on success, false otherwise.
+ */
+bool Recompiler::start()
+{
+       utf *name = utf_new_char("Recompiler");
+
+       if (!threads_thread_start_internal(name, (functionptr) &Recompiler::thread))
+               return false;
+
+       return true;
+}
+
+
+/**
+ * Add a method to the recompilation queue and signal the
+ * recompilation thread that there is some work to do.
+ *
+ * @param m Method to recompile.
+ */
+void Recompiler::queue_method(methodinfo *m)
+{
+       // Add the method to the queue.
+       _methods.push(m);
+
+       // Enter the recompile mutex, so we can call notify.
+       _mutex.lock();
+
+       // Signal the recompiler thread.
+       _cond.signal();
+
+       // Leave the mutex.
+       _mutex.unlock();
+}
+
+
+
+// Legacy C interface.
+extern "C" {
+       void Recompiler_queue_method(methodinfo* m) { VM::get_current()->get_recompiler().queue_method(m); }
+}
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
diff --git a/src/vm/jit/optimizing/recompiler.hpp b/src/vm/jit/optimizing/recompiler.hpp
new file mode 100644 (file)
index 0000000..4a99d84
--- /dev/null
@@ -0,0 +1,105 @@
+/* src/vm/jit/optimizing/recompiler.hpp - recompilation system
+
+   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 _RECOMPILER_HPP
+#define _RECOMPILER_HPP
+
+#include "config.h"
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+#include <queue>
+#endif
+
+#include "threads/condition.hpp"
+#include "threads/mutex.hpp"
+
+#include "vm/method.h"
+
+
+#ifdef __cplusplus
+
+/**
+ * Thread for JIT recompilations.
+ */
+class Recompiler {
+private:
+       Mutex                   _mutex;
+       Condition               _cond;
+       std::queue<methodinfo*> _methods;
+       bool                    _run;       ///< Flag to stop worker thread.
+
+       static void thread();               ///< Worker thread.
+
+public:
+       Recompiler() : _run(true) {}
+       ~Recompiler();
+
+       bool start();                       ///< Start the worker thread.
+       void queue_method(methodinfo* m);   ///< Queue a method for recompilation.
+};
+
+#endif
+
+/* list_method_entry **********************************************************/
+
+typedef struct list_method_entry list_method_entry;
+
+struct list_method_entry {
+       methodinfo *m;
+/*     listnode_t  linkage; */
+};
+
+
+/* function prototypes ********************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void Recompiler_queue_method(methodinfo *m);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _RECOMPILER_HPP
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
index bd43c368579dc04a8f6bb7cdaecb7c37c77e929c..2b135943f62a20f0473c95bf7340dfa646c8a183 100644 (file)
@@ -38,7 +38,7 @@
 #include "vm/types.h"
 
 #include "mm/memory.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
 
 
 /* reorder_place_next_unplaced_block *******************************************
index d76b463519aed72456924fd1beac55f60998345c..fccc8e77e6b7dc4ea1852034fa36d853af03fab2 100644 (file)
@@ -1,9 +1,7 @@
-/* src/vm/reorder.h - basic block reordering
+/* src/vm/optimizing/reorder.h - basic block reordering
 
-   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,
-   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.
 
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Christian Thalinger
-
-   Changes:
-
 */
 
 
 #define _REORDER_H
 
 #include "config.h"
-#include "vm/types.h"
 
-#include "vm/jit/jit.h"
+#include <stdbool.h>
+
+#include "vm/jit/jit.hpp"
 
 
 /* function prototypes ********************************************************/
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 bool reorder(jitdata *jd);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* _REORDER_H */
 
 
index 258fbf9f401a084d3deb0f64023a34c1378603aa..357f323f6a9d3a8e1d2d2cd2fce0d6024b3a4d73 100644 (file)
 #include "toolbox/bitvector.h"
 #include "toolbox/worklist.h"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 
-#include "vm/jit/jit.h" /* icmd_table */
+#include "vm/jit/jit.hpp" /* icmd_table */
 
 #include "vm/jit/ir/bytecode.h"
 
-#include "vm/jit/optimizing/dominators.h"
+#include "vm/jit/optimizing/dominators.hpp"
 #include "vm/jit/optimizing/graph.h"
 #include "vm/jit/optimizing/lifetimes.h"
 #include "vm/jit/optimizing/lsra.h"
index 56ba88184953ecfde3b09a9475d03250d7589834..78b488ab1e4d2a3303fe2b85b4c02bf709b1fd73 100644 (file)
@@ -1,9 +1,7 @@
 /* src/vm/jit/optimizing/ssa.h - static single assignment form header
 
-   Copyright (C) 2005 - 2007 R. Grafl, A. Krall, C. Kruegel, C. Oates,
-   R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
-   C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
-   Institut f. Computersprachen - TU Wien
+   Copyright (C) 2005, 2006, 2007, 2008
+   CACAOVM - Verein zu Foerderung der freien virtuellen Machine CACAO
 
    This file is part of CACAO.
 
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-   02111-1307, USA.
-
-   Contact: cacao@complang.tuwien.ac.at
-
-   Authors: Christian Ullrich
-
-   $Id: ssa.h$
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
 
 */
 
@@ -34,6 +26,8 @@
 #ifndef _SSA_H
 #define _SSA_H
 
+#include "config.h"
+
 #include "vm/jit/optimizing/graph.h"
 
 #if !defined(NDEBUG)
 #endif
 
 /* function prototypes */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 void ssa_init(jitdata *);
 void ssa(jitdata */* , graphdata **/);
 
+void fix_exception_handlers(jitdata *jd);
+
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* _SSA_H */
 
 /*
index 0246777420daef9c473e51785734a2d1d113e163..ad1038a853d2902b2a48a6aa5f18f49585d3250d 100644 (file)
@@ -33,7 +33,7 @@
 #include "toolbox/worklist.h"
 
 #include "vm/global.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
 
 #if 1
 #define printf(...) do { if (getenv("VERB")) printf(__VA_ARGS__); } while (0)
index 6dd7441ca78a4c0bf5379c4bc357fc22e8b350a1..3391d41dd4d2223fb82a4487d2f64b32b9da9861 100644 (file)
    * Unify access to phi args.
 */
 
-#include "vm/jit/jit.h"
+
+#include "config.h"
+
+#include "vm/jit/jit.hpp"
 #include "vm/global.h"
 #include "mm/memory.h"
-#include "mm/dumpmemory.h"
-#include "toolbox/list.h"
+#include "mm/dumpmemory.hpp"
+#include "toolbox/list.hpp"
 
 #include <limits.h>
 #include <stdio.h>
index 40e04fd6681241d1083c3ef437b11986f6339783..e79b1654d7be1452270a65c824c339a069977198 100644 (file)
 #include "toolbox/bitvector.h"
 #include "toolbox/worklist.h"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 
-#include "vm/jit/jit.h" /* icmd_table */
+#include "vm/jit/jit.hpp" /* icmd_table */
 
-#include "vm/jit/optimizing/dominators.h"
+#include "vm/jit/optimizing/dominators.hpp"
 #include "vm/jit/optimizing/graph.h"
 #include "vm/jit/optimizing/lifetimes.h"
 #include "vm/jit/optimizing/lsra.h"
index b299fab262847d29ba1d6f19464af0803e2d95c2..87fdd130f76934a7e717f966a38113915dfb6158 100644 (file)
 #include "toolbox/bitvector.h"
 #include "toolbox/worklist.h"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 
-#include "vm/jit/jit.h" /* icmd_table */
+#include "vm/jit/jit.hpp" /* icmd_table */
 
-#include "vm/jit/optimizing/dominators.h"
+#include "vm/jit/optimizing/dominators.hpp"
 #include "vm/jit/optimizing/graph.h"
 #include "vm/jit/optimizing/lifetimes.h"
 #include "vm/jit/optimizing/lsra.h"
index c693d6ec58a50143b89cbaec325ce3ea75fae24c..083470a3f6f567a778f6e00015103ffa53e60297 100644 (file)
@@ -31,8 +31,6 @@
 
 /* define architecture features ***********************************************/
 
-#define U8_AVAILABLE                     1
-
 /*  #define USEBUILTINTABLE */
 
 #define SUPPORT_DIVISION                 0
index f85b999d2b1f11c2705ba4f7dc91c697608a3e6d..67b9e923454b7320e9725bff8913b25a4aca4466 100644 (file)
 
 #include "mm/memory.h"
 
-#include "native/native.h"
+#include "native/native.hpp"
 
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
 
 #include "toolbox/logging.h"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/exceptions.hpp"
 #include "vm/global.h"
 #include "vm/linker.h"
-#include "vm/loader.h"
+#include "vm/loader.hpp"
 #include "vm/options.h"
 #include "vm/resolve.h"
 
 #endif
 
 #include "vm/string.hpp"
-#include "vm/suck.h"
+#include "vm/suck.hpp"
 
 #include "vm/jit/asmpart.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
 #include "vm/jit/parse.h"
 #include "vm/jit/loop/loop.h"
 
@@ -1463,54 +1463,38 @@ invoke_method:
 
                case BC_f2i:
 #if defined(__ALPHA__)
-                       if (!opt_noieee) {
-                               bte = builtintable_get_internal(BUILTIN_f2i);
-                               OP_BUILTIN_NO_EXCEPTION(bte);
-                       }
-                       else
+                       bte = builtintable_get_internal(BUILTIN_f2i);
+                       OP_BUILTIN_NO_EXCEPTION(bte);
+#else
+                       OP(opcode);
 #endif
-                       {
-                               OP(opcode);
-                       }
                        break;
 
                case BC_f2l:
 #if defined(__ALPHA__)
-                       if (!opt_noieee) {
-                               bte = builtintable_get_internal(BUILTIN_f2l);
-                               OP_BUILTIN_NO_EXCEPTION(bte);
-                       }
-                       else
+                       bte = builtintable_get_internal(BUILTIN_f2l);
+                       OP_BUILTIN_NO_EXCEPTION(bte);
+#else
+                       OP(opcode);
 #endif
-                       {
-                               OP(opcode);
-                       }
                        break;
 
                case BC_d2i:
 #if defined(__ALPHA__)
-                       if (!opt_noieee) {
-                               bte = builtintable_get_internal(BUILTIN_d2i);
-                               OP_BUILTIN_NO_EXCEPTION(bte);
-                       }
-                       else
+                       bte = builtintable_get_internal(BUILTIN_d2i);
+                       OP_BUILTIN_NO_EXCEPTION(bte);
+#else
+                       OP(opcode);
 #endif
-                       {
-                               OP(opcode);
-                       }
                        break;
 
                case BC_d2l:
 #if defined(__ALPHA__)
-                       if (!opt_noieee) {
-                               bte = builtintable_get_internal(BUILTIN_d2l);
-                               OP_BUILTIN_NO_EXCEPTION(bte);
-                       }
-                       else
+                       bte = builtintable_get_internal(BUILTIN_d2l);
+                       OP_BUILTIN_NO_EXCEPTION(bte);
+#else
+                       OP(opcode);
 #endif
-                       {
-                               OP(opcode);
-                       }
                        break;
 
 
index 55917d6a27db984ffbef144c7c108d196ad0699d..b10d7dad582cdea9ca75e4be02f009ba70dfd654 100644 (file)
@@ -1,9 +1,7 @@
 /* src/vm/jit/parse.h - parser header
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
-   C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
-   E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
-   J. Wenninger, Institut f. Computersprachen - TU Wien
+   Copyright (C) 1996-2005, 2006, 2008
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
 
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Author:  Christian Thalinger
-            Edwin Steiner
-
 */
 
 
@@ -37,7 +30,7 @@
 #include "vm/types.h"
 
 #include "vm/global.h"
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/codegen-common.hpp"
 
 
 /* macros for verifier checks during parsing **********************************/
 
 /* function prototypes ********************************************************/
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 bool parse(jitdata *jd);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* _PARSE_H */
 
 
diff --git a/src/vm/jit/patcher-common.c b/src/vm/jit/patcher-common.c
deleted file mode 100644 (file)
index 4128205..0000000
+++ /dev/null
@@ -1,531 +0,0 @@
-/* src/vm/jit/patcher-common.c - architecture independent code patching stuff
-
-   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 "codegen.h"                   /* for PATCHER_NOPS */
-#include "md.h"
-
-#include "mm/memory.h"
-
-#include "native/native.h"
-
-#include "threads/lock-common.h"
-
-#include "toolbox/list.h"
-#include "toolbox/logging.h"           /* XXX remove me! */
-
-#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/code.h"
-#include "vm/jit/disass.h"
-#include "vm/jit/jit.h"
-#include "vm/jit/patcher-common.h"
-
-
-/* patcher_function_list *******************************************************
-
-   This is a list which maps patcher function pointers to the according
-   names of the patcher functions. It is only usefull for debugging
-   purposes.
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-typedef struct patcher_function_list_t {
-       functionptr  patcher;
-       char        *name;
-} patcher_function_list_t;
-
-static patcher_function_list_t patcher_function_list[] = {
-       { PATCHER_initialize_class,              "initialize_class" },
-       { PATCHER_resolve_class,                 "resolve_class" },
-       { PATCHER_resolve_native_function,       "resolve_native_function" },
-       { PATCHER_invokestatic_special,          "invokestatic_special" },
-       { PATCHER_invokevirtual,                 "invokevirtual" },
-       { PATCHER_invokeinterface,               "invokeinterface" },
-       { NULL,                                  "-UNKNOWN PATCHER FUNCTION-" }
-};
-#endif
-
-
-/* patcher_list_create *********************************************************
-
-   Creates an empty patcher list for the given codeinfo.
-
-*******************************************************************************/
-
-void patcher_list_create(codeinfo *code)
-{
-       code->patchers = list_create(OFFSET(patchref_t, linkage));
-}
-
-
-/* patcher_list_reset **********************************************************
-
-   Resets the patcher list inside a codeinfo. This is usefull when
-   resetting a codeinfo for recompiling.
-
-*******************************************************************************/
-
-void patcher_list_reset(codeinfo *code)
-{
-       patchref_t *pr;
-
-       /* free all elements of the list */
-
-       while((pr = list_first(code->patchers)) != NULL) {
-               list_remove(code->patchers, pr);
-
-               FREE(pr, patchref_t);
-
-#if defined(ENABLE_STATISTICS)
-               if (opt_stat)
-                       size_patchref -= sizeof(patchref_t);
-#endif
-       }
-}
-
-/* patcher_list_free ***********************************************************
-
-   Frees the patcher list and all its entries for the given codeinfo.
-
-*******************************************************************************/
-
-void patcher_list_free(codeinfo *code)
-{
-       /* free all elements of the list */
-
-       patcher_list_reset(code);
-
-       /* free the list itself */
-
-       FREE(code->patchers, list_t);
-}
-
-
-/* patcher_list_find ***********************************************************
-
-   Find an entry inside the patcher list for the given codeinfo
-   by specifying the program counter of the patcher position.
-
-   NOTE: Caller should hold the patcher list lock or maintain
-   exclusive access otherwise.
-
-*******************************************************************************/
-
-static patchref_t *patcher_list_find(codeinfo *code, u1 *pc)
-{
-       patchref_t *pr;
-
-       /* walk through all patcher references for the given codeinfo */
-
-       pr = list_first(code->patchers);
-
-       while (pr) {
-
-/*#define TRACE_PATCHER_FIND*/
-#ifdef TRACE_PATCHER_FIND
-               log_println("patcher_list_find: %p == %p", pr->mpc, pc);
-#endif
-
-               if (pr->mpc == (ptrint) pc)
-                       return pr;
-
-               pr = list_next(code->patchers, pr);
-       }
-
-       return NULL;
-}
-
-
-/* patcher_add_patch_ref *******************************************************
-
-   Appends a new patcher reference to the list of patching positions.
-
-*******************************************************************************/
-
-void patcher_add_patch_ref(jitdata *jd, functionptr patcher, void* ref, s4 disp)
-{
-       codegendata *cd;
-       codeinfo    *code;
-       patchref_t  *pr;
-       s4           patchmpc;
-
-       cd       = jd->cd;
-       code     = jd->code;
-       patchmpc = cd->mcodeptr - cd->mcodebase;
-
-#if !defined(NDEBUG)
-       if (patcher_list_find(code, (u1 *) (intptr_t) patchmpc) != NULL)
-               vm_abort("patcher_add_patch_ref: different patchers at same position.");
-#endif
-
-       /* allocate patchref on heap (at least freed together with codeinfo) */
-
-       pr = NEW(patchref_t);
-       list_add_first(code->patchers, pr);
-
-#if defined(ENABLE_STATISTICS)
-       if (opt_stat)
-               size_patchref += sizeof(patchref_t);
-#endif
-
-       /* set patcher information (mpc is resolved later) */
-
-       pr->mpc     = patchmpc;
-       pr->disp    = disp;
-       pr->patcher = patcher;
-       pr->ref     = ref;
-       pr->mcode   = 0;
-       pr->done    = false;
-
-#if defined(ENABLE_JITCACHE)
-       pr->attached_ref = NULL;
-#endif
-
-       /* Generate NOPs for opt_shownops. */
-
-       if (opt_shownops)
-               PATCHER_NOPS;
-
-#if defined(ENABLE_JIT) && (defined(__I386__) || defined(__M68K__) || defined(__SPARC_64__) || defined(__X86_64__))
-
-       /* XXX We can remove that when we don't use UD2 anymore on i386
-          and x86_64. */
-
-       /* On some architectures the patcher stub call instruction might
-          be longer than the actual instruction generated.  On this
-          architectures we store the last patcher call position and after
-          the basic block code generation is completed, we check the
-          range and maybe generate some nop's. */
-       /* The nops are generated in codegen_emit in each codegen */
-
-       cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
-#endif
-}
-
-
-/**
- * Resolve all patchers in the current JIT run.
- *
- * @param jd JIT data-structure
- */
-void patcher_resolve(jitdata* jd)
-{
-       codeinfo*   code;
-       patchref_t* pr;
-
-       /* Get required compiler data. */
-
-       code = jd->code;
-
-       for (pr = list_first(code->patchers); pr != NULL; pr = list_next(code->patchers, pr)) {
-               pr->mpc   += (intptr_t) code->entrypoint;
-               pr->datap  = (intptr_t) (pr->disp + code->entrypoint);
-       }
-}
-
-
-/* patcher_handler *************************************************************
-
-   Handles the request to patch JIT code at the given patching
-   position. This function is normally called by the signal
-   handler.
-
-   NOTE: The patcher list lock is used to maintain exclusive
-   access of the patched position (in fact of the whole code).
-   After patching has suceeded, the patcher reference should be
-   removed from the patcher list to avoid double patching.
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-/* XXX this indent is not thread safe! */
-/* XXX if you want it thread safe, place patcher_depth in threadobject! */
-static int patcher_depth = 0;
-#define TRACE_PATCHER_INDENT for (i=0; i<patcher_depth; i++) printf("\t")
-#endif /* !defined(NDEBUG) */
-
-java_handle_t *patcher_handler(u1 *pc)
-{
-       codeinfo      *code;
-       patchref_t    *pr;
-       bool           result;
-       java_handle_t *e;
-#if !defined(NDEBUG)
-       patcher_function_list_t *l;
-       int                      i;
-#endif
-
-       /* define the patcher function */
-
-       bool (*patcher_function)(patchref_t *);
-
-       /* search the codeinfo for the given PC */
-
-       code = code_find_codeinfo_for_pc(pc);
-       assert(code);
-
-       /* enter a monitor on the patcher list */
-
-       LOCK_MONITOR_ENTER(code->patchers);
-
-       /* search the patcher information for the given PC */
-
-       pr = patcher_list_find(code, pc);
-
-       if (pr == NULL)
-               vm_abort("patcher_handler: Unable to find patcher reference.");
-
-       if (pr->done) {
-#if !defined(NDEBUG)
-               if (opt_DebugPatcher) {
-                       log_println("patcher_handler: double-patching detected!");
-               }
-#endif
-               LOCK_MONITOR_EXIT(code->patchers);
-               return NULL;
-       }
-
-#if !defined(NDEBUG)
-       if (opt_DebugPatcher) {
-               for (l = patcher_function_list; l->patcher != NULL; l++)
-                       if (l->patcher == pr->patcher)
-                               break;
-
-               TRACE_PATCHER_INDENT; printf("patching in "); method_print(code->m); printf(" at %p\n", (void *) pr->mpc);
-               TRACE_PATCHER_INDENT; printf("\tpatcher function = %s <%p>\n", l->name, (void *) (intptr_t) pr->patcher);
-
-               TRACE_PATCHER_INDENT;
-               printf("\tmachine code before = ");
-
-# if defined(ENABLE_DISASSEMBLER)
-               disassinstr((void *) pr->mpc);
-# else
-               printf("disassembler disabled\n");
-# endif
-
-               patcher_depth++;
-               assert(patcher_depth > 0);
-       }
-#endif
-
-       /* cast the passed function to a patcher function */
-
-       patcher_function = (bool (*)(patchref_t *)) (ptrint) pr->patcher;
-
-       /* call the proper patcher function */
-
-       result = (patcher_function)(pr);
-
-#if !defined(NDEBUG)
-       if (opt_DebugPatcher) {
-               assert(patcher_depth > 0);
-               patcher_depth--;
-
-               TRACE_PATCHER_INDENT;
-               printf("\tmachine code after  = ");
-
-# if defined(ENABLE_DISASSEMBLER)
-               disassinstr((void *) pr->mpc);
-# else
-               printf("disassembler disabled\n");
-# endif
-
-               if (result == false) {
-                       TRACE_PATCHER_INDENT; printf("\tPATCHER EXCEPTION!\n");
-               }
-       }
-#endif
-
-#if defined(ENABLE_JITCACHE)
-       /* Put cached reference into the code and remove it from the patcher */
-       if (pr->attached_ref)
-       {
-               jitcache_handle_cached_ref(pr->attached_ref, code);
-               pr->attached_ref = NULL;
-       }
-#endif
-
-       /* check for return value and exit accordingly */
-
-       if (result == false) {
-               e = exceptions_get_and_clear_exception();
-
-               LOCK_MONITOR_EXIT(code->patchers);
-
-               return e;
-       }
-
-       pr->done = true; /* XXX this is only preliminary to prevent double-patching */
-
-       LOCK_MONITOR_EXIT(code->patchers);
-
-       return NULL;
-}
-
-
-/* patcher_initialize_class ****************************************************
-
-   Initalizes a given classinfo pointer.
-   This function does not patch any data.
-
-*******************************************************************************/
-
-bool patcher_initialize_class(patchref_t *pr)
-{
-       classinfo *c;
-
-       /* get stuff from the patcher reference */
-
-       c = (classinfo *) pr->ref;
-
-       /* check if the class is initialized */
-
-       if (!(c->state & CLASS_INITIALIZED))
-               if (!initialize_class(c))
-                       return false;
-
-       /* patch back original code */
-
-       patcher_patch_code(pr);
-
-       return true;
-}
-
-
-/* patcher_resolve_class *******************************************************
-
-   Resolves a given unresolved class reference.
-   This function does not patch any data.
-
-*******************************************************************************/
-
-#ifdef ENABLE_VERIFIER
-bool patcher_resolve_class(patchref_t *pr)
-{
-       unresolved_class *uc;
-
-       /* get stuff from the patcher reference */
-
-       uc = (unresolved_class *) pr->ref;
-
-       /* resolve the class and check subtype constraints */
-
-       if (!resolve_class_eager_no_access_check(uc))
-               return false;
-
-       /* patch back original code */
-
-       patcher_patch_code(pr);
-
-       return true;
-}
-#endif /* ENABLE_VERIFIER */
-
-
-/* patcher_resolve_native_function *********************************************
-
-   Resolves the native function for a given methodinfo.
-   This function patches one data segment word.
-
-*******************************************************************************/
-
-bool patcher_resolve_native_function(patchref_t *pr)
-{
-       methodinfo  *m;
-       uint8_t     *datap;
-       functionptr  f;
-
-       /* get stuff from the patcher reference */
-
-       m     = (methodinfo *) pr->ref;
-       datap = (uint8_t *)    pr->datap;
-
-       /* resolve native function */
-
-       if (!(f = native_method_resolve(m)))
-               return false;
-
-       /* patch native function pointer */
-
-       *((intptr_t *) datap) = (intptr_t) f;
-
-       /* synchronize data cache */
-
-       md_dcacheflush(datap, SIZEOF_VOID_P);
-
-       /* patch back original code */
-
-       patcher_patch_code(pr);
-
-       return true;
-}
-
-/** Placeholder functions to calm down linker */
-#if defined(__I386__)
-bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
-{
-       return true;
-}
-
-bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
-{
-       return true;
-}
-
-bool patcher_resolve_classref_to_index(patchref_t *pr)
-{
-       return true;
-}
-
-bool patcher_resolve_classref_to_flags(patchref_t *pr)
-{
-       return true;
-}
-#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:
- */
-
diff --git a/src/vm/jit/patcher-common.cpp b/src/vm/jit/patcher-common.cpp
new file mode 100644 (file)
index 0000000..0a903ec
--- /dev/null
@@ -0,0 +1,556 @@
+/* src/vm/jit/patcher-common.cpp - architecture independent code patching stuff
+
+   Copyright (C) 2007, 2008
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+   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 <assert.h>
+#include <stdint.h>
+
+#include <algorithm>
+#include <functional>
+
+#include "codegen.h"                   /* for PATCHER_NOPS */
+#include "md.h"
+
+#include "mm/memory.h"
+
+#include "native/native.hpp"
+
+#include "toolbox/list.hpp"
+#include "toolbox/logging.h"           /* XXX remove me! */
+
+#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/code.hpp"
+#include "vm/jit/disass.h"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/patcher-common.hpp"
+
+
+/* patcher_function_list *******************************************************
+
+   This is a list which maps patcher function pointers to the according
+   names of the patcher functions. It is only usefull for debugging
+   purposes.
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+typedef struct patcher_function_list_t {
+       functionptr patcher;
+       const char* name;
+} patcher_function_list_t;
+
+static patcher_function_list_t patcher_function_list[] = {
+       { PATCHER_initialize_class,              "initialize_class" },
+       { PATCHER_resolve_class,                 "resolve_class" },
+       { PATCHER_resolve_native_function,       "resolve_native_function" },
+       { PATCHER_invokestatic_special,          "invokestatic_special" },
+       { PATCHER_invokevirtual,                 "invokevirtual" },
+       { PATCHER_invokeinterface,               "invokeinterface" },
+       { NULL,                                  "-UNKNOWN PATCHER FUNCTION-" }
+};
+#endif
+
+
+/* patcher_list_create *********************************************************
+
+   Creates an empty patcher list for the given codeinfo.
+
+*******************************************************************************/
+
+void patcher_list_create(codeinfo *code)
+{
+       code->patchers = new List<patchref_t>();
+}
+
+
+/* patcher_list_reset **********************************************************
+
+   Resets the patcher list inside a codeinfo. This is usefull when
+   resetting a codeinfo for recompiling.
+
+*******************************************************************************/
+
+void patcher_list_reset(codeinfo *code)
+{
+#if defined(ENABLE_STATISTICS)
+       if (opt_stat)
+               size_patchref -= sizeof(patchref_t) * code->patchers->size();
+#endif
+
+       // Free all elements of the list.
+       code->patchers->clear();
+}
+
+/* patcher_list_free ***********************************************************
+
+   Frees the patcher list and all its entries for the given codeinfo.
+
+*******************************************************************************/
+
+void patcher_list_free(codeinfo *code)
+{
+       // Free all elements of the list.
+       patcher_list_reset(code);
+
+       // Free the list itself.
+       delete code->patchers;
+}
+
+
+/**
+ * Find an entry inside the patcher list for the given codeinfo by
+ * specifying the program counter of the patcher position.
+ *
+ * NOTE: Caller should hold the patcher list lock or maintain
+ * exclusive access otherwise.
+ *
+ * @param pc Program counter to find.
+ *
+ * @return Pointer to patcher.
+ */
+
+struct foo : public std::binary_function<patchref_t, void*, bool> {
+       bool operator() (const patchref_t& pr, const void* pc) const
+       {
+               return (pr.mpc == (uintptr_t) pc);
+       }
+};
+
+static patchref_t* patcher_list_find(codeinfo* code, void* pc)
+{
+       // Search for a patcher with the given PC.
+       List<patchref_t>::iterator it = std::find_if(code->patchers->begin(), code->patchers->end(), std::bind2nd(foo(), pc));
+
+       if (it == code->patchers->end())
+               return NULL;
+
+       return &(*it);
+}
+
+
+/* patcher_add_patch_ref *******************************************************
+
+   Appends a new patcher reference to the list of patching positions.
+
+*******************************************************************************/
+
+void patcher_add_patch_ref(jitdata *jd, functionptr patcher, void* ref, s4 disp)
+{
+       codegendata *cd;
+       codeinfo    *code;
+       s4           patchmpc;
+
+       cd       = jd->cd;
+       code     = jd->code;
+       patchmpc = cd->mcodeptr - cd->mcodebase;
+
+#if !defined(NDEBUG)
+       if (patcher_list_find(code, (void*) (intptr_t) patchmpc) != NULL)
+               vm_abort("patcher_add_patch_ref: different patchers at same position.");
+#endif
+
+       // Set patcher information (mpc is resolved later).
+       patchref_t pr;
+
+       pr.mpc     = patchmpc;
+       pr.datap   = 0;
+       pr.disp    = disp;
+       pr.patcher = patcher;
+       pr.ref     = ref;
+       pr.mcode   = 0;
+       pr.done    = false;
+
+#if defined(ENABLE_JITCACHE)
+       pr.attached_ref = NULL;
+#endif
+
+       // Store patcher in the list (NOTE: structure is copied).
+       code->patchers->push_back(pr);
+
+#if defined(ENABLE_STATISTICS)
+       if (opt_stat)
+               size_patchref += sizeof(patchref_t);
+#endif
+
+#if defined(ENABLE_JIT) && (defined(__I386__) || defined(__M68K__) || defined(__SPARC_64__) || defined(__X86_64__))
+
+       /* XXX We can remove that when we don't use UD2 anymore on i386
+          and x86_64. */
+
+       /* On some architectures the patcher stub call instruction might
+          be longer than the actual instruction generated.  On this
+          architectures we store the last patcher call position and after
+          the basic block code generation is completed, we check the
+          range and maybe generate some nop's. */
+       /* The nops are generated in codegen_emit in each codegen */
+
+       cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
+#endif
+}
+
+
+/**
+ * Resolve all patchers in the current JIT run.
+ *
+ * @param jd JIT data-structure
+ */
+void patcher_resolve(jitdata* jd)
+{
+       // Get required compiler data.
+       codeinfo* code = jd->code;
+
+       for (List<patchref_t>::iterator it = code->patchers->begin(); it != code->patchers->end(); it++) {
+               patchref_t& pr = *it;
+
+               pr.mpc   += (intptr_t) code->entrypoint;
+               pr.datap  = (intptr_t) (pr.disp + code->entrypoint);
+       }
+}
+
+
+/**
+ * Check if the patcher is already patched.  This is done by comparing
+ * the machine instruction.
+ *
+ * @param pr Patcher structure.
+ *
+ * @return true if patched, false otherwise.
+ */
+bool patcher_is_patched(patchref_t* pr)
+{
+       // Validate the instruction at the patching position is the same
+       // instruction as the patcher structure contains.
+       uint32_t mcode = *((uint32_t*) pr->mpc);
+
+       if (mcode != pr->mcode) {
+               // The code differs.
+               return false;
+       }
+
+       return true;
+}
+
+
+/**
+ *
+ */
+bool patcher_is_patched_at(void* pc)
+{
+       codeinfo* code = code_find_codeinfo_for_pc(pc);
+
+       // Get the patcher for the given PC.
+       patchref_t* pr = patcher_list_find(code, pc);
+
+       if (pr == NULL) {
+               // The given PC is not a patcher position.
+               return false;
+       }
+
+       // Validate the instruction.
+       return patcher_is_patched(pr);
+}
+
+
+/* patcher_handler *************************************************************
+
+   Handles the request to patch JIT code at the given patching
+   position. This function is normally called by the signal
+   handler.
+
+   NOTE: The patcher list lock is used to maintain exclusive
+   access of the patched position (in fact of the whole code).
+   After patching has suceeded, the patcher reference should be
+   removed from the patcher list to avoid double patching.
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+/* XXX this indent is not thread safe! */
+/* XXX if you want it thread safe, place patcher_depth in threadobject! */
+static int patcher_depth = 0;
+#define TRACE_PATCHER_INDENT for (i=0; i<patcher_depth; i++) printf("\t")
+#endif /* !defined(NDEBUG) */
+
+java_handle_t *patcher_handler(u1 *pc)
+{
+       codeinfo      *code;
+       patchref_t    *pr;
+       bool           result;
+       java_handle_t *e;
+#if !defined(NDEBUG)
+       patcher_function_list_t *l;
+       int                      i;
+#endif
+
+       /* define the patcher function */
+
+       bool (*patcher_function)(patchref_t *);
+
+       /* search the codeinfo for the given PC */
+
+       code = code_find_codeinfo_for_pc(pc);
+       assert(code);
+
+       // Enter a mutex on the patcher list.
+       code->patchers->lock();
+
+       /* search the patcher information for the given PC */
+
+       pr = patcher_list_find(code, pc);
+
+       if (pr == NULL)
+               vm_abort("patcher_handler: Unable to find patcher reference.");
+
+       if (pr->done) {
+#if !defined(NDEBUG)
+               if (opt_DebugPatcher) {
+                       log_println("patcher_handler: double-patching detected!");
+               }
+#endif
+               code->patchers->unlock();
+               return NULL;
+       }
+
+#if !defined(NDEBUG)
+       if (opt_DebugPatcher) {
+               for (l = patcher_function_list; l->patcher != NULL; l++)
+                       if (l->patcher == pr->patcher)
+                               break;
+
+               TRACE_PATCHER_INDENT; printf("patching in "); method_print(code->m); printf(" at %p\n", (void *) pr->mpc);
+               TRACE_PATCHER_INDENT; printf("\tpatcher function = %s <%p>\n", l->name, (void *) (intptr_t) pr->patcher);
+
+               TRACE_PATCHER_INDENT;
+               printf("\tmachine code before = ");
+
+# if defined(ENABLE_DISASSEMBLER)
+               disassinstr((u1*) (void*) pr->mpc);
+# else
+               printf("%x at %p (disassembler disabled)\n", *((uint32_t*) pr->mpc), (void*) pr->mpc);
+# endif
+
+               patcher_depth++;
+               assert(patcher_depth > 0);
+       }
+#endif
+
+       /* cast the passed function to a patcher function */
+
+       patcher_function = (bool (*)(patchref_t *)) (ptrint) pr->patcher;
+
+       /* call the proper patcher function */
+
+       result = (patcher_function)(pr);
+
+#if !defined(NDEBUG)
+       if (opt_DebugPatcher) {
+               assert(patcher_depth > 0);
+               patcher_depth--;
+
+               TRACE_PATCHER_INDENT;
+               printf("\tmachine code after  = ");
+
+# if defined(ENABLE_DISASSEMBLER)
+               disassinstr((u1*) (void*) pr->mpc);
+# else
+               printf("%x at %p (disassembler disabled)\n", *((uint32_t*) pr->mpc), (void*) pr->mpc);
+# endif
+
+               if (result == false) {
+                       TRACE_PATCHER_INDENT; printf("\tPATCHER EXCEPTION!\n");
+               }
+       }
+#endif
+
+#if defined(ENABLE_JITCACHE)
+       /* Put cached reference into the code and remove it from the patcher */
+       if (pr->attached_ref)
+       {
+               jitcache_handle_cached_ref(pr->attached_ref, code);
+               pr->attached_ref = NULL;
+       }
+#endif
+
+       /* check for return value and exit accordingly */
+
+       if (result == false) {
+               e = exceptions_get_and_clear_exception();
+
+               code->patchers->unlock();
+
+               return e;
+       }
+
+       pr->done = true; /* XXX this is only preliminary to prevent double-patching */
+
+       code->patchers->unlock();
+
+       return NULL;
+}
+
+
+/* patcher_initialize_class ****************************************************
+
+   Initalizes a given classinfo pointer.
+   This function does not patch any data.
+
+*******************************************************************************/
+
+bool patcher_initialize_class(patchref_t *pr)
+{
+       classinfo *c;
+
+       /* get stuff from the patcher reference */
+
+       c = (classinfo *) pr->ref;
+
+       /* check if the class is initialized */
+
+       if (!(c->state & CLASS_INITIALIZED))
+               if (!initialize_class(c))
+                       return false;
+
+       /* patch back original code */
+
+       patcher_patch_code(pr);
+
+       return true;
+}
+
+
+/* patcher_resolve_class *******************************************************
+
+   Resolves a given unresolved class reference.
+   This function does not patch any data.
+
+*******************************************************************************/
+
+#ifdef ENABLE_VERIFIER
+bool patcher_resolve_class(patchref_t *pr)
+{
+       unresolved_class *uc;
+
+       /* get stuff from the patcher reference */
+
+       uc = (unresolved_class *) pr->ref;
+
+       /* resolve the class and check subtype constraints */
+
+       if (!resolve_class_eager_no_access_check(uc))
+               return false;
+
+       /* patch back original code */
+
+       patcher_patch_code(pr);
+
+       return true;
+}
+#endif /* ENABLE_VERIFIER */
+
+
+/* patcher_resolve_native_function *********************************************
+
+   Resolves the native function for a given methodinfo.
+   This function patches one data segment word.
+
+*******************************************************************************/
+
+bool patcher_resolve_native_function(patchref_t *pr)
+{
+       methodinfo  *m;
+       uint8_t     *datap;
+
+       /* get stuff from the patcher reference */
+
+       m     = (methodinfo *) pr->ref;
+       datap = (uint8_t *)    pr->datap;
+
+       /* resolve native function */
+
+       NativeMethods& nm = VM::get_current()->get_nativemethods();
+       void* f = nm.resolve_method(m);
+
+       if (f == NULL)
+               return false;
+
+       /* patch native function pointer */
+
+       *((intptr_t*) datap) = (intptr_t) f;
+
+       /* synchronize data cache */
+
+       md_dcacheflush(datap, SIZEOF_VOID_P);
+
+       /* patch back original code */
+
+       patcher_patch_code(pr);
+
+       return true;
+}
+
+/** Placeholder functions to calm down linker */
+#if defined(__I386__)
+bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
+{
+       return true;
+}
+
+bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
+{
+       return true;
+}
+
+bool patcher_resolve_classref_to_index(patchref_t *pr)
+{
+       return true;
+}
+
+bool patcher_resolve_classref_to_flags(patchref_t *pr)
+{
+       return true;
+}
+#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:
+ */
+
diff --git a/src/vm/jit/patcher-common.h b/src/vm/jit/patcher-common.h
deleted file mode 100644 (file)
index dd9d829..0000000
+++ /dev/null
@@ -1,206 +0,0 @@
-/* src/vm/jit/patcher-common.h - architecture independent code patching stuff
-
-   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 _PATCHER_COMMON_H
-#define _PATCHER_COMMON_H
-
-/* forward typedefs ***********************************************************/
-
-#include "config.h"
-#include "vm/types.h"
-
-#include "toolbox/list.h"
-
-#include "vm/global.h"
-
-#include "vm/jit/jit.h"
-
-#if defined (ENABLE_JITCACHE)
-struct cached_ref_t;
-#endif
-
-/* patchref_t ******************************************************************
-
-   A patcher reference contains information about a code position
-   which needs additional code patching during runtime.
-
-*******************************************************************************/
-
-typedef struct patchref_t {
-       ptrint       mpc;           /* absolute position in code segment          */
-       ptrint       datap;         /* absolute position in data segment          */
-       s4           disp;          /* displacement of ref in the data segment    */
-       functionptr  patcher;       /* patcher function to call                   */
-       void*        ref;           /* reference passed                           */
-       u8           mcode;         /* machine code to be patched back in         */
-       bool         done;          /* XXX preliminary: patch already applied?    */
-#if defined (ENABLE_JITCACHE)
-       struct cachedref_t *attached_ref;
-                                                               /* cached reference which must be resolved    *
-                                                                * patcher has been run.                      */
-#endif
-       listnode_t   linkage;
-} patchref_t;
-
-
-/* macros *********************************************************************/
-
-
-/* function prototypes ********************************************************/
-
-void patcher_list_create(codeinfo *code);
-void patcher_list_reset(codeinfo *code);
-void patcher_list_free(codeinfo *code);
-
-void patcher_add_patch_ref(jitdata *jd, functionptr patcher, void* ref, s4 disp);
-
-void patcher_resolve(jitdata* jd);
-
-java_handle_t *patcher_handler(u1 *pc);
-
-
-/* empty patcher (just patches back original mcode) ***************************/
-
-void patcher_patch_code(patchref_t *pr);
-
-
-/* patcher prototypes and macros **********************************************/
-
-/* new patcher functions */
-
-bool patcher_resolve_class(patchref_t *pr);
-#define PATCHER_resolve_class (functionptr) patcher_resolve_class
-
-bool patcher_initialize_class(patchref_t *pr);
-#define PATCHER_initialize_class (functionptr) patcher_initialize_class
-
-bool patcher_resolve_classref_to_classinfo(patchref_t *pr);
-#define PATCHER_resolve_classref_to_classinfo (functionptr) patcher_resolve_classref_to_classinfo
-
-bool patcher_resolve_classref_to_vftbl(patchref_t *pr);
-#define PATCHER_resolve_classref_to_vftbl (functionptr) patcher_resolve_classref_to_vftbl
-
-bool patcher_resolve_classref_to_index(patchref_t *pr);
-#define PATCHER_resolve_classref_to_index (functionptr) patcher_resolve_classref_to_index
-
-bool patcher_resolve_classref_to_flags(patchref_t *pr);
-#define PATCHER_resolve_classref_to_flags (functionptr) patcher_resolve_classref_to_flags
-
-bool patcher_resolve_native_function(patchref_t *pr);
-#define PATCHER_resolve_native_function (functionptr) patcher_resolve_native_function
-
-/* old patcher functions */
-
-bool patcher_get_putstatic(patchref_t *pr);
-#define PATCHER_get_putstatic (functionptr) patcher_get_putstatic
-
-#if defined(__I386__)
-
-bool patcher_getfield(patchref_t *pr);
-#define PATCHER_getfield (functionptr) patcher_getfield
-
-bool patcher_putfield(patchref_t *pr);
-#define PATCHER_putfield (functionptr) patcher_putfield
-
-#else
-
-bool patcher_get_putfield(patchref_t *pr);
-#define PATCHER_get_putfield (functionptr) patcher_get_putfield
-
-#endif /* defined(__I386__) */
-
-#if defined(__I386__) || defined(__X86_64__)
-
-bool patcher_putfieldconst(patchref_t *pr);
-#define PATCHER_putfieldconst (functionptr) patcher_putfieldconst
-
-#endif /* defined(__I386__) || defined(__X86_64__) */
-
-bool patcher_invokestatic_special(patchref_t *pr);
-#define PATCHER_invokestatic_special (functionptr) patcher_invokestatic_special
-
-bool patcher_invokevirtual(patchref_t *pr);
-#define PATCHER_invokevirtual (functionptr) patcher_invokevirtual
-
-bool patcher_invokeinterface(patchref_t *pr);
-#define PATCHER_invokeinterface (functionptr) patcher_invokeinterface
-
-#if defined(__ALPHA__) || defined(__I386__) || defined(__MIPS__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__S390__) || defined(__X86_64__) || defined(__M68K__)
-
-bool patcher_checkcast_interface(patchref_t *pr);
-#define PATCHER_checkcast_interface (functionptr) patcher_checkcast_interface
-
-bool patcher_instanceof_interface(patchref_t *pr);
-#define PATCHER_instanceof_interface (functionptr) patcher_instanceof_interface
-
-#endif /* defined(__ALPHA__) || defined(__I386__) || defined(__MIPS__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__S390__) || defined(__X86_64__) || defined(__M68K__) */
-
-#if defined(__S390__)
-
-bool patcher_checkcast_instanceof_interface(patchref_t *pr);
-#define PATCHER_checkcast_instanceof_interface (functionptr) patcher_checkcast_instanceof_interface
-
-#endif /* defined(__S390__) */
-
-#if defined(__I386__)
-
-bool patcher_aconst(patchref_t *pr);
-#define PATCHER_aconst (functionptr) patcher_aconst
-
-bool patcher_builtin_multianewarray(patchref_t *pr);
-#define PATCHER_builtin_multianewarray (functionptr) patcher_builtin_multianewarray
-
-bool patcher_builtin_arraycheckcast(patchref_t *pr);
-#define PATCHER_builtin_arraycheckcast (functionptr) patcher_builtin_arraycheckcast
-
-bool patcher_checkcast_instanceof_flags(patchref_t *pr);
-#define PATCHER_checkcast_instanceof_flags (functionptr) patcher_checkcast_instanceof_flags
-
-bool patcher_checkcast_class(patchref_t *pr);
-#define PATCHER_checkcast_class (functionptr) patcher_checkcast_class
-
-bool patcher_instanceof_class(patchref_t *pr);
-#define PATCHER_instanceof_class (functionptr) patcher_instanceof_class
-
-#endif /* defined(__I386__) */
-
-void patch_md(s4 md_patch, ptrint dest, void* ref);
-
-#endif /* _PATCHER_COMMON_H */
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
diff --git a/src/vm/jit/patcher-common.hpp b/src/vm/jit/patcher-common.hpp
new file mode 100644 (file)
index 0000000..7a10d4d
--- /dev/null
@@ -0,0 +1,224 @@
+/* src/vm/jit/patcher-common.hpp - architecture independent code patching stuff
+
+   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 _PATCHER_COMMON_HPP
+#define _PATCHER_COMMON_HPP
+
+/* forward typedefs ***********************************************************/
+
+typedef struct cachedref_t cachedref_t;
+typedef struct patchref_t patchref_t;
+
+#include "config.h"
+#include "vm/types.h"
+
+#include "toolbox/list.hpp"
+
+#include "vm/global.h"
+
+#include "vm/jit/jit.hpp"
+
+#if defined (ENABLE_JITCACHE)
+struct cached_ref_t;
+#endif
+
+/* patchref_t ******************************************************************
+
+   A patcher reference contains information about a code position
+   which needs additional code patching during runtime.
+
+*******************************************************************************/
+
+struct patchref_t {
+       ptrint       mpc;           /* absolute position in code segment          */
+       ptrint       datap;         /* absolute position in data segment          */
+       s4           disp;          /* displacement of ref in the data segment    */
+       functionptr  patcher;       /* patcher function to call                   */
+       void*        ref;           /* reference passed                           */
+       uint32_t     mcode;         /* machine code to be patched back in         */
+       bool         done;          /* XXX preliminary: patch already applied?    */
+#if defined (ENABLE_JITCACHE)
+       cachedref_t  *attached_ref;
+                                                               /* cached reference which must be resolved    *
+                                                                * patcher has been run.                      */
+#endif
+};
+
+
+/* macros *********************************************************************/
+
+
+/* function prototypes ********************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void patcher_list_create(codeinfo *code);
+void patcher_list_reset(codeinfo *code);
+void patcher_list_free(codeinfo *code);
+
+void patcher_add_patch_ref(jitdata *jd, functionptr patcher, void* ref, s4 disp);
+
+void patcher_resolve(jitdata* jd);
+
+bool patcher_is_patched(patchref_t* pr);
+bool patcher_is_patched_at(void* pc);
+
+// MD function.
+bool patcher_is_valid_trap_instruction_at(void* pc);
+
+java_handle_t *patcher_handler(u1 *pc);
+
+
+/* empty patcher (just patches back original mcode) ***************************/
+
+void patcher_patch_code(patchref_t *pr);
+
+
+/* patcher prototypes and macros **********************************************/
+
+/* new patcher functions */
+
+bool patcher_resolve_class(patchref_t *pr);
+#define PATCHER_resolve_class (functionptr) patcher_resolve_class
+
+bool patcher_initialize_class(patchref_t *pr);
+#define PATCHER_initialize_class (functionptr) patcher_initialize_class
+
+bool patcher_resolve_classref_to_classinfo(patchref_t *pr);
+#define PATCHER_resolve_classref_to_classinfo (functionptr) patcher_resolve_classref_to_classinfo
+
+bool patcher_resolve_classref_to_vftbl(patchref_t *pr);
+#define PATCHER_resolve_classref_to_vftbl (functionptr) patcher_resolve_classref_to_vftbl
+
+bool patcher_resolve_classref_to_index(patchref_t *pr);
+#define PATCHER_resolve_classref_to_index (functionptr) patcher_resolve_classref_to_index
+
+bool patcher_resolve_classref_to_flags(patchref_t *pr);
+#define PATCHER_resolve_classref_to_flags (functionptr) patcher_resolve_classref_to_flags
+
+bool patcher_resolve_native_function(patchref_t *pr);
+#define PATCHER_resolve_native_function (functionptr) patcher_resolve_native_function
+
+/* old patcher functions */
+
+bool patcher_get_putstatic(patchref_t *pr);
+#define PATCHER_get_putstatic (functionptr) patcher_get_putstatic
+
+#if defined(__I386__)
+
+bool patcher_getfield(patchref_t *pr);
+#define PATCHER_getfield (functionptr) patcher_getfield
+
+bool patcher_putfield(patchref_t *pr);
+#define PATCHER_putfield (functionptr) patcher_putfield
+
+#else
+
+bool patcher_get_putfield(patchref_t *pr);
+#define PATCHER_get_putfield (functionptr) patcher_get_putfield
+
+#endif /* defined(__I386__) */
+
+#if defined(__I386__) || defined(__X86_64__)
+
+bool patcher_putfieldconst(patchref_t *pr);
+#define PATCHER_putfieldconst (functionptr) patcher_putfieldconst
+
+#endif /* defined(__I386__) || defined(__X86_64__) */
+
+bool patcher_invokestatic_special(patchref_t *pr);
+#define PATCHER_invokestatic_special (functionptr) patcher_invokestatic_special
+
+bool patcher_invokevirtual(patchref_t *pr);
+#define PATCHER_invokevirtual (functionptr) patcher_invokevirtual
+
+bool patcher_invokeinterface(patchref_t *pr);
+#define PATCHER_invokeinterface (functionptr) patcher_invokeinterface
+
+#if defined(__ALPHA__) || defined(__I386__) || defined(__MIPS__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__S390__) || defined(__X86_64__) || defined(__M68K__)
+
+bool patcher_checkcast_interface(patchref_t *pr);
+#define PATCHER_checkcast_interface (functionptr) patcher_checkcast_interface
+
+bool patcher_instanceof_interface(patchref_t *pr);
+#define PATCHER_instanceof_interface (functionptr) patcher_instanceof_interface
+
+#endif /* defined(__ALPHA__) || defined(__I386__) || defined(__MIPS__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__S390__) || defined(__X86_64__) || defined(__M68K__) */
+
+#if defined(__S390__)
+
+bool patcher_checkcast_instanceof_interface(patchref_t *pr);
+#define PATCHER_checkcast_instanceof_interface (functionptr) patcher_checkcast_instanceof_interface
+
+#endif /* defined(__S390__) */
+
+#if defined(__I386__)
+
+bool patcher_aconst(patchref_t *pr);
+#define PATCHER_aconst (functionptr) patcher_aconst
+
+bool patcher_builtin_multianewarray(patchref_t *pr);
+#define PATCHER_builtin_multianewarray (functionptr) patcher_builtin_multianewarray
+
+bool patcher_builtin_arraycheckcast(patchref_t *pr);
+#define PATCHER_builtin_arraycheckcast (functionptr) patcher_builtin_arraycheckcast
+
+bool patcher_checkcast_instanceof_flags(patchref_t *pr);
+#define PATCHER_checkcast_instanceof_flags (functionptr) patcher_checkcast_instanceof_flags
+
+bool patcher_checkcast_class(patchref_t *pr);
+#define PATCHER_checkcast_class (functionptr) patcher_checkcast_class
+
+bool patcher_instanceof_class(patchref_t *pr);
+#define PATCHER_instanceof_class (functionptr) patcher_instanceof_class
+
+#endif /* defined(__I386__) */
+
+#if defined (__ARM__)
+void patch_md(s4 md_patch, ptrint dest, void* ref);
+#endif /* defined(__ARM__) */
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _PATCHER_COMMON_HPP
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
index 448fdde343784cb376dd1b4d2ff457bae82b7679..730fb9d8f6cf74de04fea6cdd51418576b3b9105 100644 (file)
@@ -53,6 +53,7 @@ libarch_la_SOURCES = \
        emit.c \
        patcher.c \
        \
+       md-stubs.hpp \
        md-trap.h \
        md.c \
        md.h
index 13f7b158b11c9bce60a144be3756dbd4b198f9c8..ca0efa5a4512997f72f226678d00135147e684d8 100644 (file)
@@ -35,8 +35,6 @@
 
 /* define architecture features ***********************************************/
 
-#define U8_AVAILABLE                     1
-
 #define SUPPORT_DIVISION                 1
 #define SUPPORT_LONG                     1
 
index f8d36f10cd03a0181785ebd35e650a6dd9c62bf7..c7431f8093f8e55f21936929a789a482a51a3352 100644 (file)
 
 #include "mm/memory.h"
 
-#include "native/localref.h"
-#include "native/native.h"
+#include "native/localref.hpp"
+#include "native/native.hpp"
 
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/exceptions.hpp"
 #include "vm/global.h"
-#include "vm/loader.h"
+#include "vm/loader.hpp"
 #include "vm/options.h"
 #include "vm/vm.hpp"
 
 #include "vm/jit/abi.h"
 #include "vm/jit/abi-asm.h"
 #include "vm/jit/asmpart.h"
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/codegen-common.hpp"
 #include "vm/jit/dseg.h"
-#include "vm/jit/emit-common.h"
-#include "vm/jit/jit.h"
-#include "vm/jit/linenumbertable.h"
+#include "vm/jit/emit-common.hpp"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/linenumbertable.hpp"
 #include "vm/jit/methodheader.h"
 #include "vm/jit/parse.h"
-#include "vm/jit/patcher-common.h"
+#include "vm/jit/patcher-common.hpp"
 #include "vm/jit/reg.h"
-#include "vm/jit/replace.h"
+#include "vm/jit/replace.hpp"
 #include "vm/jit/stacktrace.hpp"
 #include "vm/jit/trap.h"
 
index ea6f9843546d91b19d233bc4ddc1d7abc1c85215..8ed75e85cb5c91cacd3420f036c4c2830930059c 100644 (file)
@@ -32,7 +32,7 @@
 #include "md-abi.h"
 
 #include "vm/global.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
 #include "vm/jit/reg.h"
 
 
     } while (0)
 
 
-/* stub defines ***************************************************************/
-
-#define COMPILERSTUB_CODESIZE    1 * 4
-
-
 /* macros to create code ******************************************************/
 
 #define M_OP3(opcode,y,oe,rc,d,a,b) \
 #define MI_and(rA,rS,rB)                M_OP3(31,  28, 0, 0, rS, rA, rB)
 #define MI_anddot(rA,rS,rB)             M_OP3(31,  28, 0, 1, rS, rA, rB)
 #define MI_andi(rA,rS,UIMM)             M_OP2_IMM(28, rS, rA, UIMM)
+#define MI_illegal                      M_OP3( 0,   0, 0, 0,  0,  0,  0)
 #define MI_lwarx(rD,rA,rB)              M_OP3(31,  20, 0, 0, rD, rA, rB)
 #define MI_or(rA,rS,rB)                 M_OP3(31, 444, 0, 0, rS, rA, rB)
 #define MI_ordot(rA,rS,rB)              M_OP3(31, 444, 0, 1, rS, rA, rB)
 
 #define M_IAND(a,b,d)                   MI_and(d, a, b)
 #define M_IAND_IMM(a,b,d)               MI_andi(d, a, b)
+#define M_ILLEGAL                       MI_illegal
 #define M_IOR(a,b,d)                    MI_or(d, a, b)
 #define M_IOR_IMM(a,b,d)                MI_ori(d, a, b)
 #define M_IOR_TST(a,b,d)                MI_ordot(d, a, b)
index 1f026257b055ac7161263a768bb9dd0f4039b6ca..d2e6bf2313e963153948df503ede60f17255d6aa 100644 (file)
@@ -37,7 +37,7 @@
 
 #include "threads/thread.hpp"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/global.h"
 #include "vm/signallocal.h"
 
index 17cb85c1ae77355ad7e1d6743c8dd8bbf73b04ca..66221d67d115adbbdcd0aeec1ce1697bb31027db 100644 (file)
 
 #include "mm/memory.h"
 
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
 
 #include "vm/options.h"
 
 #include "vm/jit/abi.h"
 #include "vm/jit/asmpart.h"
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/codegen-common.hpp"
 #include "vm/jit/dseg.h"
-#include "vm/jit/emit-common.h"
-#include "vm/jit/jit.h"
-#include "vm/jit/replace.h"
+#include "vm/jit/emit-common.hpp"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/replace.hpp"
 #include "vm/jit/trace.hpp"
 #include "vm/jit/trap.h"
 
@@ -344,36 +344,46 @@ void emit_branch(codegendata *cd, s4 disp, s4 condition, s4 reg, u4 opt)
                                                          CODEGENDATA_FLAG_LONGBRANCHES);
                        }
 
-                       switch (condition) {
-                       case BRANCH_EQ:
-                               M_BNE(1);
-                               M_BR(branchdisp);
-                               break;
-                       case BRANCH_NE:
-                               M_BEQ(1);
-                               M_BR(branchdisp);
-                               break;
-                       case BRANCH_LT:
-                               M_BGE(1);
-                               M_BR(branchdisp);
-                               break;
-                       case BRANCH_GE:
-                               M_BLT(1);
-                               M_BR(branchdisp);
-                               break;
-                       case BRANCH_GT:
-                               M_BLE(1);
-                               M_BR(branchdisp);
-                               break;
-                       case BRANCH_LE:
-                               M_BGT(1);
-                               M_BR(branchdisp);
-                               break;
-                       case BRANCH_NAN:
-                               vm_abort("emit_branch: long BRANCH_NAN");
-                               break;
-                       default:
-                               vm_abort("emit_branch: unknown condition %d", condition);
+                       // Subtract 1 instruction from the displacement as the
+                       // actual branch is the second instruction.
+                       checkdisp  = checkdisp - 4;
+                       branchdisp = branchdisp - 1;
+
+                       if ((checkdisp < (int32_t) 0xfe000000) || (checkdisp > (int32_t) 0x01fffffc)) {
+                               vm_abort("emit_branch: emit conditional long-branch code");
+                       }
+                       else {
+                               switch (condition) {
+                               case BRANCH_EQ:
+                                       M_BNE(1);
+                                       M_BR(branchdisp);
+                                       break;
+                               case BRANCH_NE:
+                                       M_BEQ(1);
+                                       M_BR(branchdisp);
+                                       break;
+                               case BRANCH_LT:
+                                       M_BGE(1);
+                                       M_BR(branchdisp);
+                                       break;
+                               case BRANCH_GE:
+                                       M_BLT(1);
+                                       M_BR(branchdisp);
+                                       break;
+                               case BRANCH_GT:
+                                       M_BLE(1);
+                                       M_BR(branchdisp);
+                                       break;
+                               case BRANCH_LE:
+                                       M_BGT(1);
+                                       M_BR(branchdisp);
+                                       break;
+                               case BRANCH_NAN:
+                                       vm_abort("emit_branch: long BRANCH_NAN");
+                                       break;
+                               default:
+                                       vm_abort("emit_branch: unknown condition %d", condition);
+                               }
                        }
                }
                else {
@@ -533,14 +543,11 @@ void emit_trap_compiler(codegendata *cd)
 
 uint32_t emit_trap(codegendata *cd)
 {
-       uint32_t mcode;
-
-       /* Get machine code which is patched back in later. The
-          trap is 1 instruction word long. */
-
-       mcode = *((uint32_t *) cd->mcodeptr);
+       // Get machine code which is patched back in later. The rap is 1
+       // instruction word long.
+       uint32_t mcode = *((uint32_t*) cd->mcodeptr);
 
-       M_ALD_INTERN(REG_ZERO, REG_ZERO, TRAP_PATCHER);
+       M_ILLEGAL;
 
        return mcode;
 }
index cfa9704080fe6fd00a7d7f4c709e8a7d92ef5ef9..e59a84cbb1813b29b7e3f0194d8b4877e7041f74 100644 (file)
@@ -2,6 +2,7 @@
 
    Copyright (C) 1996-2005, 2006, 2007, 2008
    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+   Copyright (C) 2008 Theobroma Systems Ltd.
 
    This file is part of CACAO.
 
 
 #include "threads/thread.hpp"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/signallocal.h"
 #include "vm/os.hpp"
 
 #include "vm/jit/asmpart.h"
+#include "vm/jit/disass.h"
 #include "vm/jit/executionstate.h"
 
 #if defined(ENABLE_PROFILING)
 # include "vm/jit/optimizing/profile.h"
 #endif
 
+#include "vm/jit/patcher-common.hpp"
 #include "vm/jit/trap.h"
 
 
@@ -73,7 +76,6 @@ void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
        intptr_t        addr;
        intptr_t        val;
        int             type;
-       void           *p;
 
        _uc = (ucontext_t *) _p;
 
@@ -124,43 +126,59 @@ void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
 
        /* Handle the trap. */
 
-       p = trap_handle(type, val, pv, sp, ra, xpc, _p);
-
-       /* Set registers. */
+       trap_handle(type, val, pv, sp, ra, xpc, _p);
+}
 
-       switch (type) {
-       case TRAP_COMPILER:
-               if (p != NULL) {
-                       _gregs[REG_PV] = (uintptr_t) p;
-                       _gregs[PT_NIP] = (uintptr_t) p;
-                       break;
-               }
 
-               /* Get and set the PV from the parent Java method. */
+/**
+ * Signal handler for patcher calls.
+ */
+void md_signal_handler_sigill(int sig, siginfo_t* siginfo, void* _p)
+{
+       ucontext_t* _uc = (ucontext_t*) _p;
+       mcontext_t* _mc;
+       unsigned long* _gregs;
 
-               pv = md_codegen_get_pv_from_pc(ra);
+#if defined(__UCLIBC__)
+       _mc    = &(_uc->uc_mcontext);
+       _gregs = _mc->regs->gpr;
+#else
+       _mc    = _uc->uc_mcontext.uc_regs;
+       _gregs = _mc->gregs;
+#endif
 
-               _gregs[REG_PV] = (uintptr_t) pv;
+       /* get register values */
 
-               /* Get the exception object. */
+       void* pv = (void*) _gregs[REG_PV];
+       void* sp = (void*) _gregs[REG_SP];
+       void* ra = (void*) _gregs[PT_LNK]; // The RA is correct for leag methods.
+       void* xpc =(void*) _gregs[PT_NIP];
 
-               p = builtin_retrieve_exception();
+       // Get the illegal-instruction.
+       uint32_t mcode = *((uint32_t*) xpc);
 
-               assert(p != NULL);
+       // Check if the trap instruction is valid.
+       // TODO Move this into patcher_handler.
+       if (patcher_is_valid_trap_instruction_at(xpc) == false) {
+               // Check if the PC has been patched during our way to this
+               // signal handler (see PR85).
+               if (patcher_is_patched_at(xpc) == true)
+                       return;
 
-               /* fall-through */
+               // We have a problem...
+               log_println("md_signal_handler_sigill: Unknown illegal instruction 0x%x at 0x%lx", mcode, xpc);
+#if defined(ENABLE_DISASSEMBLER)
+               (void) disassinstr(xpc);
+#endif
+               vm_abort("Aborting...");
+       }
 
-       case TRAP_PATCHER:
-               if (p == NULL)
-                       break;
+       // This signal is always a patcher.
+       int      type = TRAP_PATCHER;
+       intptr_t val  = 0;
 
-               /* fall-through */
-               
-       default:
-               _gregs[REG_ITMP1_XPTR] = (uintptr_t) p;
-               _gregs[REG_ITMP2_XPC]  = (uintptr_t) xpc;
-               _gregs[PT_NIP]         = (uintptr_t) asm_handle_exception;
-       }
+       // Handle the trap.
+       trap_handle(type, val, pv, sp, ra, xpc, _p);
 }
 
 
@@ -183,7 +201,6 @@ void md_signal_handler_sigtrap(int sig, siginfo_t *siginfo, void *_p)
        int             s1;
        intptr_t        val;
        int             type;
-       void           *p;
 
        _uc = (ucontext_t *) _p;
 
@@ -213,13 +230,7 @@ void md_signal_handler_sigtrap(int sig, siginfo_t *siginfo, void *_p)
 
        /* Handle the trap. */
 
-       p = trap_handle(type, val, pv, sp, ra, xpc, _p);
-
-       /* Set registers. */
-
-       _gregs[REG_ITMP1_XPTR] = (uintptr_t) p;
-       _gregs[REG_ITMP2_XPC]  = (uintptr_t) xpc;
-       _gregs[PT_NIP]         = (uintptr_t) asm_handle_exception;
+       trap_handle(type, val, pv, sp, ra, xpc, _p);
 }
 
 
diff --git a/src/vm/jit/powerpc/md-stubs.hpp b/src/vm/jit/powerpc/md-stubs.hpp
new file mode 100644 (file)
index 0000000..caf3cc6
--- /dev/null
@@ -0,0 +1,56 @@
+/* src/vm/jit/powerpc/md-stubs.hpp - PowerPC JIT stubs
+
+   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 _MD_STUBS_HPP
+#define _MD_STUBS_HPP
+
+#include "config.h"
+
+
+/**
+ * Return the code size of a compiler on a PowerPC architecture.
+ *
+ * @return Code size in bytes.
+ */
+int CompilerStub::get_code_size()
+{
+       return 1 * 4;
+}
+
+#endif // _MD_STUBS_HPP
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
index 80257ab60cc5e958d33c29123feec1cf6c70ad0d..3595f407a4c2688c48b44d5e280a53e974c7329f 100644 (file)
@@ -37,7 +37,7 @@
 #include "vm/global.h"
 #include "vm/vm.hpp"
 
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
 
 
 /* md_init *********************************************************************
index dbf367765b12b5bab33d59c36610af40d070f948..33724ab14ae24b774b90f4536e4fcb9448d95a1e 100644 (file)
@@ -37,7 +37,7 @@
 #include "vm/vm.hpp"
 
 #include "vm/jit/asmpart.h"
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/codegen-common.hpp"
 
 
 /* md_stacktrace_get_returnaddress *********************************************
index 13b50d814ca6df25c48ce7438fc3fbb07404fc59..0dc24cadd927788661a136b216916118a60a106c 100644 (file)
@@ -2,6 +2,7 @@
 
    Copyright (C) 1996-2005, 2006, 2007, 2008
    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+   Copyright (C) 2008 Theobroma Systems Ltd.
 
    This file is part of CACAO.
 
 
 #include "mm/memory.h"
 
-#include "native/native.h"
+#include "native/native.hpp"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/class.h"
-#include "vm/field.h"
+#include "vm/field.hpp"
 #include "vm/initialize.h"
 #include "vm/options.h"
 #include "vm/references.h"
 
 #include "vm/jit/asmpart.h"
 #include "vm/jit/methodheader.h"
-#include "vm/jit/patcher-common.h"
-
-
-#define PATCH_BACK_ORIGINAL_MCODE \
-       *((u4 *) pr->mpc) = (u4) pr->mcode; \
-       md_icacheflush((u1 *) pr->mpc, 4);
+#include "vm/jit/patcher-common.hpp"
 
 
 /* patcher_patch_code **********************************************************
 
 void patcher_patch_code(patchref_t *pr)
 {
-       PATCH_BACK_ORIGINAL_MCODE;
+       // Patch back original code.
+       *((uint32_t*) pr->mpc) = pr->mcode;
+
+       // Synchronize instruction cache.
+       md_icacheflush((void*) pr->mpc, 1 * 4);
+}
+
+
+/**
+ * Check if the trap instruction at the given PC is valid.
+ *
+ * @param pc Program counter.
+ *
+ * @return true if valid, false otherwise.
+ */
+bool patcher_is_valid_trap_instruction_at(void* pc)
+{
+       uint32_t mcode = *((uint32_t*) pc);
+
+       // Check for the undefined instruction we use.
+       return (mcode == 0x00000000);
 }
 
 
@@ -99,30 +115,24 @@ void patcher_patch_code(patchref_t *pr)
 
 bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
 {
-       constant_classref *cr;
-       u1                *datap;
-       classinfo         *c;
-
-       /* get stuff from the stack */
+       constant_classref * cr    = (constant_classref*) pr->ref;
+       uintptr_t*          datap = (uintptr_t*)         pr->datap;
 
-       cr    = (constant_classref *) pr->ref;
-       datap = (u1 *)                pr->datap;
+       // Resolve the class.
+       classinfo* c = resolve_classref_eager(cr);
 
-       /* get the classinfo */
-
-       if (!(c = resolve_classref_eager(cr)))
+       if (c == NULL)
                return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
-
-       /* patch the classinfo pointer */
-
-       *((ptrint *) datap) = (ptrint) c;
-
-       /* synchronize data cache */
+       // Patch the class pointer.
+       *datap = (uintptr_t) c;
 
+       // Synchronize data cache.
        md_dcacheflush(datap, SIZEOF_VOID_P);
 
+       // Patch back the original code.
+       patcher_patch_code(pr);
+
        return true;
 }
 
@@ -147,30 +157,24 @@ bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
 
 bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
 {
-       constant_classref *cr;
-       u1                *datap;
-       classinfo         *c;
+       constant_classref* cr    = (constant_classref*) pr->ref;
+       uintptr_t*         datap = (uintptr_t*)         pr->datap;
 
-       /* get stuff from the stack */
+       // Resolve the class.
+       classinfo* c = resolve_classref_eager(cr);
 
-       cr    = (constant_classref *) pr->ref;
-       datap = (u1 *)                pr->datap;
-
-       /* get the fieldinfo */
-
-       if (!(c = resolve_classref_eager(cr)))
+       if (c == NULL)
                return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
-
-       /* patch super class' vftbl */
-
-       *((ptrint *) datap) = (ptrint) c->vftbl;
-
-       /* synchronize data cache */
+       // Patch super class' vftbl.
+       *datap = (uintptr_t) c->vftbl;
 
+       // Synchronize data cache.
        md_dcacheflush(datap, SIZEOF_VOID_P);
 
+       // Patch back the original code.
+       patcher_patch_code(pr);
+
        return true;
 }
 
@@ -186,30 +190,24 @@ bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
 
 bool patcher_resolve_classref_to_flags(patchref_t *pr)
 {
-       constant_classref *cr;
-       u1                *datap;
-       classinfo         *c;
-
-       /* get stuff from the stack */
-
-       cr    = (constant_classref *) pr->ref;
-       datap = (u1 *)                pr->datap;
+       constant_classref* cr    = (constant_classref*) pr->ref;
+       int32_t*           datap = (int32_t*)           pr->datap;
 
-       /* get the fieldinfo */
+       // Resolve the class.
+       classinfo* c = resolve_classref_eager(cr);
 
-       if (!(c = resolve_classref_eager(cr)))
+       if (c == NULL)
                return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
-
-       /* patch class flags */
-
-       *((s4 *) datap) = (s4) c->flags;
-
-       /* synchronize data cache */
+       // Patch class flags.
+       *datap = c->flags;
 
+       // Synchronize data cache.
        md_dcacheflush(datap, SIZEOF_VOID_P);
 
+       // Patch back the original code.
+       patcher_patch_code(pr);
+
        return true;
 }
 
@@ -226,38 +224,29 @@ bool patcher_resolve_classref_to_flags(patchref_t *pr)
 
 bool patcher_get_putstatic(patchref_t *pr)
 {
-       u1               *ra;
-       unresolved_field *uf;
-       u1               *datap;
-       fieldinfo        *fi;
-
-       /* get stuff from the stack */
+       unresolved_field* uf    = (unresolved_field*) pr->ref;
+       uintptr_t*        datap = (uintptr_t*)        pr->datap;
 
-       ra    = (u1 *)                pr->mpc;
-       uf    = (unresolved_field *)  pr->ref;
-       datap = (u1 *)                pr->datap;
+       // Resolve the field.
+       fieldinfo* fi = resolve_field_eager(uf);
 
-       /* get the fieldinfo */
-
-       if (!(fi = resolve_field_eager(uf)))
+       if (fi == NULL)
                return false;
 
-       /* check if the field's class is initialized */
-
+       // Check if the field's class is initialized.
        if (!(fi->clazz->state & CLASS_INITIALIZED))
                if (!initialize_class(fi->clazz))
                        return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
-
-       /* patch the field value's address */
-
-       *((intptr_t *) datap) = (intptr_t) fi->value;
-
-       /* synchronize data cache */
+       // Patch the field value's address.
+       *datap = (uintptr_t) fi->value;
 
+       // Synchronize data cache.
        md_dcacheflush(datap, SIZEOF_VOID_P);
 
+       // Patch back the original code.
+       patcher_patch_code(pr);
+
        return true;
 }
 
@@ -273,53 +262,44 @@ bool patcher_get_putstatic(patchref_t *pr)
 
 bool patcher_get_putfield(patchref_t *pr)
 {
-       u1               *ra;
-       unresolved_field *uf;
-       fieldinfo        *fi;
-       s2                disp;
-
-       ra = (u1 *)               pr->mpc;
-       uf = (unresolved_field *) pr->ref;
+       uint32_t*         pc = (uint32_t*)         pr->mpc;
+       unresolved_field* uf = (unresolved_field*) pr->ref;
 
-       /* get the fieldinfo */
+       // Resolve the field.
+       fieldinfo* fi = resolve_field_eager(uf);
 
-       if (!(fi = resolve_field_eager(uf)))
+       if (fi == NULL)
                return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
-
-       /* if we show NOPs, we have to skip them */
-
-       if (opt_shownops)
-               ra = ra + 1 * 4;
-
-       /* patch the field's offset */
-
+       // Patch the field's offset.
        if (IS_LNG_TYPE(fi->type)) {
                /* If the field has type long, we have to patch two
                   instructions.  But we have to check which instruction
                   is first.  We do that with the offset of the first
                   instruction. */
 
-               disp = *((u4 *) (ra + 0 * 4));
+               uint32_t disp = (pr->mcode & 0x0000ffff);
 
                if (disp == 4) {
-                       *((u4 *) (ra + 0 * 4)) &= 0xffff0000;
-                       *((u4 *) (ra + 0 * 4)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
-                       *((u4 *) (ra + 1 * 4)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
+                       pr->mcode &= 0xffff0000;
+                       pr->mcode |= ((fi->offset + 4) & 0x0000ffff);
+                       pc[1] |= ((fi->offset + 0) & 0x0000ffff);
                }
                else {
-                       *((u4 *) (ra + 0 * 4)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
-                       *((u4 *) (ra + 1 * 4)) &= 0xffff0000;
-                       *((u4 *) (ra + 1 * 4)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
+                       pr->mcode |= ((fi->offset + 0) & 0x0000ffff);
+                       pc[1] &= 0xffff0000;
+                       pc[1] |= ((fi->offset + 4) & 0x0000ffff);
                }
-       }
-       else
-               *((u4 *) (ra + 0 * 4)) |= (s2) (fi->offset & 0x0000ffff);
 
-       /* synchronize instruction cache */
+               // Synchronize instruction cache.
+               md_icacheflush(pc + 1, 1 * 4);
+       }
+       else {
+               pr->mcode |= (fi->offset & 0x0000ffff);
+       }
 
-       md_icacheflush(ra + 0 * 4, 2 * 4);
+       // Patch back the original code.
+       patcher_patch_code(pr);
 
        return true;
 }
@@ -338,30 +318,24 @@ bool patcher_get_putfield(patchref_t *pr)
 
 bool patcher_invokestatic_special(patchref_t *pr)
 {
-       unresolved_method *um;
-       u1                *datap;
-       methodinfo        *m;
-
-       /* get stuff from the stack */
+       unresolved_method* um    = (unresolved_method*) pr->ref;
+       uintptr_t*         datap = (uintptr_t*)         pr->datap;
 
-       um    = (unresolved_method *) pr->ref;
-       datap = (u1 *)                pr->datap;
+       // Resolve the method.
+       methodinfo* m = resolve_method_eager(um);
 
-       /* get the fieldinfo */
-
-       if (!(m = resolve_method_eager(um)))
+       if (m == NULL)
                return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
-
-       /* patch stubroutine */
-
-       *((ptrint *) datap) = (ptrint) m->stubroutine;
-
-       /* synchronize data cache */
+       // Patch stubroutine.
+       *datap = (uintptr_t) m->stubroutine;
 
+       // Synchronize data cache.
        md_dcacheflush(datap, SIZEOF_VOID_P);
 
+       // Patch back the original code.
+       patcher_patch_code(pr);
+
        return true;
 }
 
@@ -380,37 +354,25 @@ bool patcher_invokestatic_special(patchref_t *pr)
 
 bool patcher_invokevirtual(patchref_t *pr)
 {
-       u1                *ra;
-       unresolved_method *um;
-       methodinfo        *m;
-       s4                 disp;
-
-       /* get stuff from the stack */
-
-       ra = (u1 *)                pr->mpc;
-       um = (unresolved_method *) pr->ref;
+       uint32_t*          pc = (uint32_t*)          pr->mpc;
+       unresolved_method* um = (unresolved_method*) pr->ref;
 
-       /* get the fieldinfo */
+       // Resolve the method.
+       methodinfo* m = resolve_method_eager(um);
 
-       if (!(m = resolve_method_eager(um)))
+       if (m == NULL)
                return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
+       // Patch vftbl index.
+       int32_t disp = (OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex);
 
-       /* if we show NOPs, we have to skip them */
+       pc[1] |= (disp & 0x0000ffff);
 
-       if (opt_shownops)
-               ra = ra + 1 * 4;
+       // Synchronize instruction cache.
+       md_icacheflush(pc + 1, 1 * 4);
 
-       /* patch vftbl index */
-
-       disp = (OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex);
-
-       *((s4 *) (ra + 1 * 4)) |= (disp & 0x0000ffff);
-
-       /* synchronize instruction cache */
-
-       md_icacheflush(ra + 1 * 4, 1 * 4);
+       // Patch back the original code.
+       patcher_patch_code(pr);
 
        return true;
 }
@@ -431,48 +393,32 @@ bool patcher_invokevirtual(patchref_t *pr)
 
 bool patcher_invokeinterface(patchref_t *pr)
 {
-       u1                *ra;
-       unresolved_method *um;
-       methodinfo        *m;
-       s4                 disp;
-
-       /* get stuff from the stack */
+       uint32_t*          pc = (uint32_t*)          pr->mpc;
+       unresolved_method* um = (unresolved_method*) pr->ref;
 
-       ra = (u1 *)                pr->mpc;
-       um = (unresolved_method *) pr->ref;
+       // Resolve the method.
+       methodinfo* m = resolve_method_eager(um);
 
-       /* get the fieldinfo */
-
-       if (!(m = resolve_method_eager(um)))
+       if (m == NULL)
                return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
-
-       /* if we show NOPs, we have to skip them */
-
-       if (opt_shownops)
-               ra = ra + 1 * 4;
-
-       /* patch interfacetable index */
-
-       disp = OFFSET(vftbl_t, interfacetable[0]) -
-               sizeof(methodptr*) * m->clazz->index;
+       // Patch interfacetable index.
+       int32_t disp = OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr*) * m->clazz->index;
 
        /* XXX TWISTI: check displacement */
+       pc[1] |= (disp & 0x0000ffff);
 
-       *((s4 *) (ra + 1 * 4)) |= (disp & 0x0000ffff);
-
-       /* patch method offset */
-
+       // Patch method offset.
        disp = sizeof(methodptr) * (m - m->clazz->methods);
 
        /* XXX TWISTI: check displacement */
+       pc[2] |= (disp & 0x0000ffff);
 
-       *((s4 *) (ra + 2 * 4)) |= (disp & 0x0000ffff);
-
-       /* synchronize instruction cache */
+       // Synchronize instruction cache.
+       md_icacheflush(pc + 1, 2 * 4);
 
-       md_icacheflush(ra + 1 * 4, 2 * 4);
+       // Patch back the original code.
+       patcher_patch_code(pr);
 
        return true;
 }
@@ -494,41 +440,27 @@ bool patcher_invokeinterface(patchref_t *pr)
 
 bool patcher_checkcast_interface(patchref_t *pr)
 {
-       u1                *ra;
-       constant_classref *cr;
-       classinfo         *c;
-       s4                 disp;
-
-       /* get stuff from the stack */
-
-       ra = (u1 *)                pr->mpc;
-       cr = (constant_classref *) pr->ref;
+       uint32_t*          pc = (uint32_t*)          pr->mpc;
+       constant_classref* cr = (constant_classref*) pr->ref;
 
-       /* get the fieldinfo */
+       // Resolve the class.
+       classinfo* c = resolve_classref_eager(cr);
 
-       if (!(c = resolve_classref_eager(cr)))
+       if (c == NULL)
                return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
-
-       /* if we show NOPs, we have to skip them */
-
-       if (opt_shownops)
-               ra = ra + 1 * 4;
-
-       /* patch super class index */
-
-       disp = -(c->index);
-
-       *((s4 *) (ra + 2 * 4)) |= (disp & 0x0000ffff);
+       // Patch super class index.
+       int32_t disp = -(c->index);
+       pc[2] |= (disp & 0x0000ffff);
 
        disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
+       pc[5] |= (disp & 0x0000ffff);
 
-       *((s4 *) (ra + 5 * 4)) |= (disp & 0x0000ffff);
+       // Synchronize instruction cache.
+       md_icacheflush(pc + 2, 4 * 4);
 
-       /* synchronize instruction cache */
-
-       md_icacheflush(ra + 2 * 4, 4 * 4);
+       // Patch back the original code.
+       patcher_patch_code(pr);
 
        return true;
 }
@@ -550,41 +482,27 @@ bool patcher_checkcast_interface(patchref_t *pr)
 
 bool patcher_instanceof_interface(patchref_t *pr)
 {
-       u1                *ra;
-       constant_classref *cr;
-       classinfo         *c;
-       s4                 disp;
-
-       /* get stuff from the stack */
-
-       ra = (u1 *)                pr->mpc;
-       cr = (constant_classref *) pr->ref;
+       uint32_t*          pc = (uint32_t*)          pr->mpc;
+       constant_classref* cr = (constant_classref*) pr->ref;
 
-       /* get the fieldinfo */
+       // Resolve the class.
+       classinfo* c = resolve_classref_eager(cr);
 
-       if (!(c = resolve_classref_eager(cr)))
+       if (c == NULL)
                return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
-
-       /* if we show NOPs, we have to skip them */
-
-       if (opt_shownops)
-               ra = ra + 1 * 4;
-
-       /* patch super class index */
-
-       disp = -(c->index);
-
-       *((s4 *) (ra + 2 * 4)) |= (disp & 0x0000ffff);
+       // Patch super class index.
+       int32_t disp = -(c->index);
+       pc[2] |= (disp & 0x0000ffff);
 
        disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
+       pc[4] |= (disp & 0x0000ffff);
 
-       *((s4 *) (ra + 4 * 4)) |= (disp & 0x0000ffff);
-
-       /* synchronize instruction cache */
+       // Synchronize instruction cache.
+       md_icacheflush(pc + 2, 3 * 4);
 
-       md_icacheflush(ra + 2 * 4, 3 * 4);
+       // Patch back the original code.
+       patcher_patch_code(pr);
 
        return true;
 }
index a450512ac5942dca5904ad4c3be681234213b500..d61007a20e7fc08952f0892612d312901eca1fc6 100644 (file)
@@ -50,6 +50,7 @@ libarch_la_SOURCES = \
        emit.c \
        patcher.c \
        \
+       md-stubs.hpp \
        md-trap.h \
        md.c \
        md.h
index 5c7daa42bdd70b2b6bfd1fb6f806b89cbf7dfefc..33651985ca75c0977c2b1ae805475f0d7a753ea0 100644 (file)
@@ -35,8 +35,6 @@
 
 /* define architecture features ***********************************************/
 
-#define U8_AVAILABLE                     1
-
 #define SUPPORT_DIVISION                 1
 #define SUPPORT_LONG                     1
 
index aac1b5707e2d75fc69f6171c4842734ca4691896..64855d6dd251ea2f17006d65f4b63c5df5890590 100644 (file)
 
 #include "mm/memory.h"
 
-#include "native/localref.h"
-#include "native/native.h"
+#include "native/localref.hpp"
+#include "native/native.hpp"
 
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/exceptions.hpp"
 #include "vm/global.h"
-#include "vm/loader.h"
+#include "vm/loader.hpp"
 #include "vm/options.h"
 #include "vm/vm.hpp"
 
 #include "vm/jit/abi.h"
 #include "vm/jit/abi-asm.h"
 #include "vm/jit/asmpart.h"
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/codegen-common.hpp"
 #include "vm/jit/dseg.h"
-#include "vm/jit/emit-common.h"
-#include "vm/jit/jit.h"
-#include "vm/jit/linenumbertable.h"
+#include "vm/jit/emit-common.hpp"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/linenumbertable.hpp"
 #include "vm/jit/parse.h"
-#include "vm/jit/patcher-common.h"
+#include "vm/jit/patcher-common.hpp"
 #include "vm/jit/reg.h"
-#include "vm/jit/replace.h"
+#include "vm/jit/replace.hpp"
 #include "vm/jit/stacktrace.hpp"
 #include "vm/jit/trap.h"
 
index 1ffe1bfd91a3c5d5aa975f92ea1ebf90e4d08795..df9120f088af2393c10f792277c962306969c9c5 100644 (file)
@@ -1,10 +1,8 @@
-/* src/vm/jit/powerpc64/codegen.h - code generation macros and definitions for
-                                 64-bit PowerPC
+/* src/vm/jit/powerpc64/codegen.h - code generation macros and
+                                    definitions for PowerPC64
 
-   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.
 
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Andreas Krall
-            Stefan Ring
-            Christian Thalinger
-            Christian Ullrich
-
-
 */
 
 
@@ -42,7 +32,7 @@
 #include "md-abi.h"
 
 #include "vm/global.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
 #include "vm/jit/reg.h"
 
 
     } while (0)
 
 
-/* stub defines ***************************************************************/
-
-#define COMPILERSTUB_CODESIZE    1 * 4
-
-
 /* macros to create code ******************************************************/
 
 #define M_OP3(opcode,y,oe,rc,d,a,b) \
 
 /* instruction macros *********************************************************/
 
-#define M_IADD(a,b,c)                  M_LADD(a,b,c)
+#define M_ILLEGAL                       M_OP3(0, 0, 0, 0, 0, 0, 0)
+#define M_IADD(a,b,c)                   M_LADD(a,b,c)
 #define M_LADD(a,b,c)                   M_OP3(31, 266, 0, 0, c, a, b) 
 #define M_IADD_IMM(a,b,c)               M_OP2_IMM(14, c, a, b) /* XXX */
 #define M_LADD_IMM(a,b,c)               M_OP2_IMM(14, c, a, b)
index 26f2147600a0ede5786f1cada4d0c23c45be3a3f..4e7a37f718c21b0200688098c29e828f78dc7257 100644 (file)
 #include "md-abi.h"
 #include "vm/jit/powerpc64/codegen.h"
 
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
 
 #include "vm/options.h"
 #include "vm/vm.hpp"
 
 #include "vm/jit/abi.h"
 #include "vm/jit/asmpart.h"
-#include "vm/jit/emit-common.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/emit-common.hpp"
+#include "vm/jit/jit.hpp"
 #include "vm/jit/trace.hpp"
 #include "vm/jit/trap.h"
 
@@ -429,39 +429,47 @@ void emit_branch(codegendata *cd, s4 disp, s4 condition, s4 reg, u4 opt)
                                                          CODEGENDATA_FLAG_LONGBRANCHES);
                        }
 
-                       branchdisp --;          /* we jump from the second instruction */
-                       switch (condition) {
-                       case BRANCH_EQ:
-                               M_BNE(1);
-                               M_BR(branchdisp);
-                               break;
-                       case BRANCH_NE:
-                               M_BEQ(1);
-                               M_BR(branchdisp);
-                               break;
-                       case BRANCH_LT:
-                               M_BGE(1);
-                               M_BR(branchdisp);
-                               break;
-                       case BRANCH_GE:
-                               M_BLT(1);
-                               M_BR(branchdisp);
-                               break;
-                       case BRANCH_GT:
-                               M_BLE(1);
-                               M_BR(branchdisp);
-                               break;
-                       case BRANCH_LE:
-                               M_BGT(1);
-                               M_BR(branchdisp);
-                               break;
-                       case BRANCH_NAN:
-                               vm_abort("emit_branch: long BRANCH_NAN");
-                               break;
-                       default:
-                               vm_abort("emit_branch: unknown condition %d", condition);
-                       }
+                       // Subtract 1 instruction from the displacement as the
+                       // actual branch is the second instruction.
+                       checkdisp  = checkdisp - 4;
+                       branchdisp = branchdisp - 1;
 
+                       if ((checkdisp < (int32_t) 0xfe000000) || (checkdisp > (int32_t) 0x01fffffc)) {
+                               vm_abort("emit_branch: emit conditional long-branch code");
+                       }
+                       else {
+                               switch (condition) {
+                               case BRANCH_EQ:
+                                       M_BNE(1);
+                                       M_BR(branchdisp);
+                                       break;
+                               case BRANCH_NE:
+                                       M_BEQ(1);
+                                       M_BR(branchdisp);
+                                       break;
+                               case BRANCH_LT:
+                                       M_BGE(1);
+                                       M_BR(branchdisp);
+                                       break;
+                               case BRANCH_GE:
+                                       M_BLT(1);
+                                       M_BR(branchdisp);
+                                       break;
+                               case BRANCH_GT:
+                                       M_BLE(1);
+                                       M_BR(branchdisp);
+                                       break;
+                               case BRANCH_LE:
+                                       M_BGT(1);
+                                       M_BR(branchdisp);
+                                       break;
+                               case BRANCH_NAN:
+                                       vm_abort("emit_branch: long BRANCH_NAN");
+                                       break;
+                               default:
+                                       vm_abort("emit_branch: unknown condition %d", condition);
+                               }
+                       }
                }
                else {
                        switch (condition) {
@@ -627,15 +635,11 @@ void emit_trap_compiler(codegendata *cd)
 
 uint32_t emit_trap(codegendata *cd)
 {
-       uint32_t mcode;
-
-       /* Get machine code which is patched back in later. The
-          trap is 1 instruction word long. */
-
-       mcode = *((uint32_t *) cd->mcodeptr);
+       // Get machine code which is patched back in later. The trap is 1
+       // instruction word long.
+       uint32_t mcode = *((uint32_t*) cd->mcodeptr);
 
-       /* ALD is 4 byte aligned, ILD 2, only LWZ is byte aligned */
-       M_LWZ(REG_ZERO, REG_ZERO, TRAP_PATCHER);
+       M_ILLEGAL;
 
        return mcode;
 }
index e3821b7d01af5400daec2c7680d78373f9d52000..ebb284b4410cf7cba3fbd8fedef59dcdf2363d7a 100644 (file)
@@ -2,6 +2,7 @@
 
    Copyright (C) 1996-2005, 2006, 2007, 2008
    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+   Copyright (C) 2008 Theobroma Systems Ltd.
 
    This file is part of CACAO.
 
@@ -37,7 +38,7 @@
 
 #include "threads/thread.hpp"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/signallocal.h"
 #include "vm/os.hpp"
 
@@ -48,6 +49,7 @@
 # include "vm/jit/optimizing/profile.h"
 #endif
 
+#include "vm/jit/disass.h"
 #include "vm/jit/trap.h"
 
 
@@ -72,7 +74,6 @@ void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
        int             type;
        intptr_t        addr;
        intptr_t        val;
-       void           *p;
 
        _uc = (ucontext_t *) _p;
        _mc = &(_uc->uc_mcontext);
@@ -113,43 +114,50 @@ void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
 
        /* Handle the trap. */
 
-       p = trap_handle(type, val, pv, sp, ra, xpc, _p);
-
-       /* Set registers. */
-
-       switch (type) {
-       case TRAP_COMPILER:
-               if (p != NULL) {
-                       _mc->gp_regs[REG_PV] = (uintptr_t) p;
-                       _mc->gp_regs[PT_NIP] = (uintptr_t) p;
-                       break;
-               }
-
-               /* Get and set the PV from the parent Java method. */
-
-               pv = md_codegen_get_pv_from_pc(ra);
-
-               _mc->gp_regs[REG_PV] = (uintptr_t) pv;
+       trap_handle(type, val, pv, sp, ra, xpc, _p);
+}
 
-               /* Get the exception object. */
 
-               p = builtin_retrieve_exception();
+/**
+ * Signal handler for patcher calls.
+ */
+void md_signal_handler_sigill(int sig, siginfo_t* siginfo, void* _p)
+{
+       ucontext_t* _uc = (ucontext_t*) _p;
+       mcontext_t* _mc = &(_uc->uc_mcontext);
 
-               assert(p != NULL);
+       /* get register values */
 
-               /* fall-through */
+       void* pv = (void*) _mc->gp_regs[REG_PV];
+       void* sp = (void*) _mc->gp_regs[REG_SP];
+       void* ra = (void*) _mc->gp_regs[PT_LNK]; // The RA is correct for leag methods.
+       void* xpc =(void*) _mc->gp_regs[PT_NIP];
+
+       // Get the illegal-instruction.
+       uint32_t mcode = *((uint32_t*) xpc);
+
+       // Check if the trap instruction is valid.
+       // TODO Move this into patcher_handler.
+       if (patcher_is_valid_trap_instruction_at(xpc) == false) {
+               // Check if the PC has been patched during our way to this
+               // signal handler (see PR85).
+               if (patcher_is_patched_at(xpc) == true)
+                       return;
+
+               // We have a problem...
+               log_println("md_signal_handler_sigill: Unknown illegal instruction 0x%x at 0x%lx", mcode, xpc);
+#if defined(ENABLE_DISASSEMBLER)
+               (void) disassinstr(xpc);
+#endif
+               vm_abort("Aborting...");
+       }
 
-       case TRAP_PATCHER:
-               if (p == NULL)
-                       break;
+       // This signal is always a patcher.
+       int      type = TRAP_PATCHER;
+       intptr_t val  = 0;
 
-               /* fall-through */
-               
-       default:
-               _mc->gp_regs[REG_ITMP1_XPTR] = (uintptr_t) p;
-               _mc->gp_regs[REG_ITMP2_XPC]  = (uintptr_t) xpc;
-               _mc->gp_regs[PT_NIP]         = (uintptr_t) asm_handle_exception;
-       }
+       // Handle the trap.
+       trap_handle(type, val, pv, sp, ra, xpc, _p);
 }
 
 
@@ -187,36 +195,31 @@ void md_signal_handler_sigusr2(int sig, siginfo_t *siginfo, void *_p)
 
 void md_executionstate_read(executionstate_t *es, void *context)
 {
-#if 0
        ucontext_t    *_uc;
        mcontext_t    *_mc;
-       unsigned long *_gregs;
        s4              i;
 
        _uc = (ucontext_t *) context;
-
-       _mc    = _uc->uc_mcontext.uc_regs;
-       _gregs = _mc->gregs;
+       _mc = &(_uc->uc_mcontext);
 
        /* read special registers */
-       es->pc = (u1 *) _gregs[PT_NIP];
-       es->sp = (u1 *) _gregs[REG_SP];
-       es->pv = (u1 *) _gregs[REG_PV];
-       es->ra = (u1 *) _gregs[PT_LNK];
+       es->pc = (u1 *) _mc->gp_regs[PT_NIP];
+       es->sp = (u1 *) _mc->gp_regs[REG_SP];
+       es->pv = (u1 *) _mc->gp_regs[REG_PV];
+       es->ra = (u1 *) _mc->gp_regs[PT_LNK];
 
        /* read integer registers */
        for (i = 0; i < INT_REG_CNT; i++)
-               es->intregs[i] = _gregs[i];
+               es->intregs[i] = _mc->gp_regs[i];
 
        /* read float registers */
        /* Do not use the assignment operator '=', as the type of
         * the _mc->fpregs[i] can cause invalid conversions. */
 
-       assert(sizeof(_mc->fpregs.fpregs) == sizeof(es->fltregs));
-       os_memcpy(&es->fltregs, &_mc->fpregs.fpregs, sizeof(_mc->fpregs.fpregs));
-#endif
-
-       vm_abort("md_executionstate_read: IMPLEMENT ME!");
+       // The assertion below will fail because _mc->fp_regs[] also
+       // contains the "fpscr" register.
+       //assert(sizeof(_mc->fp_regs) == sizeof(es->fltregs));
+       os_memcpy(&es->fltregs, &_mc->fp_regs, sizeof(es->fltregs));
 }
 
 
@@ -228,36 +231,31 @@ void md_executionstate_read(executionstate_t *es, void *context)
 
 void md_executionstate_write(executionstate_t *es, void *context)
 {
-#if 0
        ucontext_t    *_uc;
        mcontext_t    *_mc;
-       unsigned long *_gregs;
        s4              i;
 
        _uc = (ucontext_t *) context;
-
-       _mc    = _uc->uc_mcontext.uc_regs;
-       _gregs = _mc->gregs;
+       _mc = &(_uc->uc_mcontext);
 
        /* write integer registers */
        for (i = 0; i < INT_REG_CNT; i++)
-               _gregs[i] = es->intregs[i];
+               _mc->gp_regs[i] = es->intregs[i];
 
        /* write float registers */
        /* Do not use the assignment operator '=', as the type of
         * the _mc->fpregs[i] can cause invalid conversions. */
 
-       assert(sizeof(_mc->fpregs.fpregs) == sizeof(es->fltregs));
-       os_memcpy(&_mc->fpregs.fpregs, &es->fltregs, sizeof(_mc->fpregs.fpregs));
+       // The assertion below will fail because _mc->fp_regs[] also
+       // contains the "fpscr" register.
+       //assert(sizeof(_mc->fp_regs) == sizeof(es->fltregs));
+       os_memcpy(&_mc->fp_regs, &es->fltregs, sizeof(es->fltregs));
 
        /* write special registers */
-       _gregs[PT_NIP] = (ptrint) es->pc;
-       _gregs[REG_SP] = (ptrint) es->sp;
-       _gregs[REG_PV] = (ptrint) es->pv;
-       _gregs[PT_LNK] = (ptrint) es->ra;
-#endif
-
-       vm_abort("md_executionstate_write: IMPLEMENT ME!");
+       _mc->gp_regs[PT_NIP] = (ptrint) es->pc;
+       _mc->gp_regs[REG_SP] = (ptrint) es->sp;
+       _mc->gp_regs[REG_PV] = (ptrint) es->pv;
+       _mc->gp_regs[PT_LNK] = (ptrint) es->ra;
 }
 
 
diff --git a/src/vm/jit/powerpc64/md-stubs.hpp b/src/vm/jit/powerpc64/md-stubs.hpp
new file mode 100644 (file)
index 0000000..5356f7f
--- /dev/null
@@ -0,0 +1,56 @@
+/* src/vm/jit/powerpc64/md-stubs.hpp - PowerPC64 JIT stubs
+
+   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 _MD_STUBS_HPP
+#define _MD_STUBS_HPP
+
+#include "config.h"
+
+
+/**
+ * Return the code size of a compiler on a PowerPC64 architecture.
+ *
+ * @return Code size in bytes.
+ */
+int CompilerStub::get_code_size()
+{
+       return 1 * 4;
+}
+
+#endif // _MD_STUBS_HPP
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
index dad8d1f7dfcab9b9cfc2d0b56e136edee12b4e1f..3830d1598ef9eb95c94cd248c7182f98105675bf 100644 (file)
@@ -53,13 +53,15 @@ enum {
 
        TRAP_ClassCastException             = 5,
        TRAP_CHECK_EXCEPTION                = 6,
-       TRAP_PATCHER                        = 7,
+       TRAP_COMPILER                       = 7,
 
        /* Don't use 8 (could be a normal load offset). */
 
-       TRAP_COMPILER                       = 9,
-       TRAP_COUNTDOWN                      = 10,
-       TRAP_END
+       TRAP_COUNTDOWN                      = 9,
+       TRAP_END,
+
+       // This handled via SIGILL.
+       TRAP_PATCHER                        = 99 // A large number.
 };
 
 #endif /* _MD_TRAP_H */
index 842937ca3291b323200efc483da1aa2c45198f70..15b564227e38b010872290989fd36e2874bfdd83 100644 (file)
@@ -39,7 +39,7 @@
 
 #include "vm/global.h"
 
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
 #include "vm/jit/trap.h"
 
 
index 992f8439d5c53627c591c37475ee8ff0fb19f3e8..b70509f86130e849b1ef14677104dc89303e045c 100644 (file)
@@ -37,7 +37,7 @@
 #include "vm/vm.hpp"
 
 #include "vm/jit/asmpart.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
 
 
 /* md_stacktrace_get_returnaddress *********************************************
index c7c1eae6cafc932fc94f39b1c8777b6dc9ec8626..117e2332d4a74bcfc598e125e8959d4e720f3f4e 100644 (file)
@@ -2,6 +2,7 @@
 
    Copyright (C) 1996-2005, 2006, 2007, 2008
    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+   Copyright (C) 2008 Theobroma Systems Ltd.
 
    This file is part of CACAO.
 
 
 #include "mm/memory.h"
 
-#include "native/native.h"
+#include "native/native.hpp"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/class.h"
-#include "vm/field.h"
+#include "vm/field.hpp"
 #include "vm/initialize.h"
 #include "vm/options.h"
 #include "vm/references.h"
@@ -46,7 +47,7 @@
 
 #include "vm/jit/asmpart.h"
 #include "vm/jit/methodheader.h"
-#include "vm/jit/patcher-common.h"
+#include "vm/jit/patcher-common.hpp"
 
 
 /* patcher_patch_code **********************************************************
 
 void patcher_patch_code(patchref_t *pr)
 {
-       /* patch back original code */
+       // Patch back original code.
+       *((uint32_t*) pr->mpc) = pr->mcode;
+
+       // Synchronize instruction cache.
+       md_icacheflush((void*) pr->mpc, 1 * 4);
+}
 
-       *((u4 *) pr->mpc) = pr->mcode;
 
-       /* synchronize instruction cache */
+/**
+ * Check if the trap instruction at the given PC is valid.
+ *
+ * @param pc Program counter.
+ *
+ * @return true if valid, false otherwise.
+ */
+bool patcher_is_valid_trap_instruction_at(void* pc)
+{
+       uint32_t mcode = *((uint32_t*) pc);
 
-       md_icacheflush(pr->mpc, 4);
+       // Check for the undefined instruction we use.
+       return (mcode == 0x00000000);
 }
 
 
@@ -77,48 +92,31 @@ void patcher_patch_code(patchref_t *pr)
 
 *******************************************************************************/
 
-bool patcher_get_putstatic(patchref_t *pr)
+bool patcher_get_putstatic(patchref_tpr)
 {
-       u1               *ra;
-       u4                mcode;
-       unresolved_field *uf;
-       u1               *datap;
-       fieldinfo        *fi;
-
-       /* get stuff from the stack */
-
-       ra    = (u1 *)                pr->mpc;
-       mcode =                       pr->mcode;
-       uf    = (unresolved_field *)  pr->ref;
-       datap = (u1 *)                pr->datap;
+       unresolved_field* uf    = (unresolved_field*) pr->ref;
+       uintptr_t*        datap = (uintptr_t*)        pr->datap;
 
-       /* get the fieldinfo */
+       // Resolve the field.
+       fieldinfo* fi = resolve_field_eager(uf);
 
-       if (!(fi = resolve_field_eager(uf)))
+       if (fi == NULL)
                return false;
 
-       /* check if the field's class is initialized */
-
+       // Check if the field's class is initialized.
        if (!(fi->clazz->state & CLASS_INITIALIZED))
                if (!initialize_class(fi->clazz))
                        return false;
 
-       /* patch back original code */
-
-       *((u4 *) ra) = mcode;
-
-       /* synchronize instruction cache */
-
-       md_icacheflush(ra, 4);
-
-       /* patch the field value's address */
-
-       *((intptr_t *) datap) = (intptr_t) fi->value;
-
-       /* synchronize data cache */
+       // Patch the field value's address.
+       *datap = (uintptr_t) fi->value;
 
+       // Synchronize data cache.
        md_dcacheflush(datap, SIZEOF_VOID_P);
 
+       // Patch back the original code.
+       patcher_patch_code(pr);
+
        return true;
 }
 
@@ -132,42 +130,22 @@ bool patcher_get_putstatic(patchref_t *pr)
 
 *******************************************************************************/
 
-bool patcher_get_putfield(patchref_t *pr)
+bool patcher_get_putfield(patchref_tpr)
 {
-       u1               *ra;
-       u4                mcode;
-       unresolved_field *uf;
-       fieldinfo        *fi;
-
-       ra    = (u1 *)                pr->mpc;
-       mcode =                       pr->mcode;
-       uf    = (unresolved_field *)  pr->ref;
+       unresolved_field* uf = (unresolved_field*) pr->ref;
 
-       /* get the fieldinfo */
+       // Resolve the field.
+       fieldinfo* fi = resolve_field_eager(uf);
 
-       if (!(fi = resolve_field_eager(uf)))
+       if (fi == NULL)
                return false;
 
-       /* patch back original code */
-
-       *((u4 *) ra) = mcode;
-
-       /* synchronize instruction cache */
-
-       md_icacheflush(ra, 4);
+       // Patch the field offset in the patcher.  We also need this to
+       // validate patchers.
+       pr->mcode |= (int16_t) (fi->offset & 0x0000ffff);
 
-       /* if we show disassembly, we have to skip the nop */
-
-       if (opt_shownops)
-               ra = ra + 4;
-
-       /* patch the field's offset */
-
-       *((u4 *) ra) |= (s2) (fi->offset & 0x0000ffff);
-
-       /* synchronize instruction cache */
-
-       md_icacheflush(ra, 8);
+       // Patch back the original code.
+       patcher_patch_code(pr);
 
        return true;
 }
@@ -184,42 +162,26 @@ bool patcher_get_putfield(patchref_t *pr)
 
 ******************************************************************************/
 
-bool patcher_invokestatic_special(patchref_t *pr)
+bool patcher_invokestatic_special(patchref_tpr)
 {
-       u1                *ra;
-       u4                 mcode;
-       unresolved_method *um;
-       u1                *datap;
-       methodinfo        *m;
-
-       /* get stuff from the stack */
+       unresolved_method* um    = (unresolved_method*) pr->ref;
+       uintptr_t*         datap = (uintptr_t*)         pr->datap;
 
-       ra    = (u1 *)                pr->mpc;
-       mcode =                       pr->mcode;
-       um    = (unresolved_method *) pr->ref;
-       datap = (u1 *)                pr->datap;
+       // Resolve the method.
+       methodinfo* m = resolve_method_eager(um);
 
-       /* get the fieldinfo */
-
-       if (!(m = resolve_method_eager(um)))
+       if (m == NULL)
                return false;
 
-       /* patch back original code */
-
-       *((u4 *) ra) = mcode;
-
-       /* synchronize instruction cache */
-
-       md_icacheflush(ra, 4);
-
-       /* patch stubroutine */
-
-       *((ptrint *) datap) = (ptrint) m->stubroutine;
-
-       /* synchronize data cache */
+       // Patch stubroutine.
+       *datap = (uintptr_t) m->stubroutine;
 
+       // Synchronize data cache.
        md_dcacheflush(datap, SIZEOF_VOID_P);
 
+       // Patch back the original code.
+       patcher_patch_code(pr);
+
        return true;
 }
 
@@ -236,47 +198,27 @@ bool patcher_invokestatic_special(patchref_t *pr)
 
 *******************************************************************************/
 
-bool patcher_invokevirtual(patchref_t *pr)
+bool patcher_invokevirtual(patchref_tpr)
 {
-       u1                *ra;
-       u4                 mcode;
-       unresolved_method *um;
-       methodinfo        *m;
-       s4                 disp;
-
-       /* get stuff from the stack */
+       uint32_t*          pc = (uint32_t*)          pr->mpc;
+       unresolved_method* um = (unresolved_method*) pr->ref;
 
-       ra    = (u1 *)                pr->mpc;
-       mcode =                       pr->mcode;
-       um    = (unresolved_method *) pr->ref;
+       // Resolve the method.
+       methodinfo* m = resolve_method_eager(um);
 
-       /* get the fieldinfo */
-
-       if (!(m = resolve_method_eager(um)))
+       if (m == NULL)
                return false;
 
-       /* patch back original code */
-
-       *((u4 *) ra) = mcode;
-
-       /* synchronize instruction cache */
+       // Patch vftbl index.
+       int32_t disp = (OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex);
 
-       md_icacheflush(ra, 4);
+       pc[1] |= (disp & 0x0000ffff);
 
-       /* if we show disassembly, we have to skip the nop */
+       // Synchronize instruction cache.
+       md_icacheflush(pc + 1, 1 * 4);
 
-       if (opt_shownops)
-               ra = ra + 4;
-
-       /* patch vftbl index */
-
-       disp = (OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex);
-
-       *((s4 *) (ra + 4)) |= (disp & 0x0000ffff);
-
-       /* synchronize instruction cache */
-
-       md_icacheflush(ra, 2 * 4);
+       // Patch back the original code.
+       patcher_patch_code(pr);
 
        return true;
 }
@@ -295,58 +237,34 @@ bool patcher_invokevirtual(patchref_t *pr)
 
 *******************************************************************************/
 
-bool patcher_invokeinterface(patchref_t *pr)
+bool patcher_invokeinterface(patchref_tpr)
 {
-       u1                *ra;
-       u4                 mcode;
-       unresolved_method *um;
-       methodinfo        *m;
-       s4                 disp;
-
-       /* get stuff from the stack */
+       uint32_t*          pc = (uint32_t*)          pr->mpc;
+       unresolved_method* um = (unresolved_method*) pr->ref;
 
-       ra    = (u1 *)                pr->mpc;
-       mcode =                       pr->mcode;
-       um    = (unresolved_method *) pr->ref;
+       // Resolve the method.
+       methodinfo* m = resolve_method_eager(um);
 
-       /* get the fieldinfo */
-
-       if (!(m = resolve_method_eager(um)))
+       if (m == NULL)
                return false;
 
-       /* patch back original code */
-
-       *((u4 *) ra) = mcode;
-
-       /* synchronize instruction cache */
-
-       md_icacheflush(ra, 4);
-
-       /* if we show disassembly, we have to skip the nop */
-
-       if (opt_shownops)
-               ra = ra + 4;
+       // Patch interfacetable index.
+       int32_t disp = OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr*) * m->clazz->index;
 
-       /* patch interfacetable index */
-
-       disp = OFFSET(vftbl_t, interfacetable[0]) -
-               sizeof(methodptr*) * m->clazz->index;
-
-       /* XXX TWISTI: check displacement */
-
-       *((s4 *) (ra + 1 * 4)) |= (disp & 0x0000ffff);
-
-       /* patch method offset */
+       // XXX TWISTI: check displacement
+       pc[1] |= (disp & 0x0000ffff);
 
+       // Patch method offset.
        disp = sizeof(methodptr) * (m - m->clazz->methods);
 
-       /* XXX TWISTI: check displacement */
-
-       *((s4 *) (ra + 2 * 4)) |= (disp & 0x0000ffff);
+       // XXX TWISTI: check displacement
+       pc[2] |= (disp & 0x0000ffff);
 
-       /* synchronize instruction cache */
+       // Synchronize instruction cache.
+       md_icacheflush(pc + 1, 2 * 4);
 
-       md_icacheflush(ra, 3 * 4);
+       // Patch back the original code.
+       patcher_patch_code(pr);
 
        return true;
 }
@@ -366,46 +284,29 @@ bool patcher_invokeinterface(patchref_t *pr)
 
 *******************************************************************************/
 
-bool patcher_checkcast_interface(patchref_t *pr)
+bool patcher_checkcast_interface(patchref_tpr)
 {
-       u1                *ra;
-       constant_classref *cr;
-       classinfo         *c;
-       s4                 disp;
-       u4                 mcode;
-
-       /* get stuff from stack */
-       ra    = (u1 *)                pr->mpc;
-       mcode =                       pr->mcode;
-       cr    = (constant_classref *) pr->ref;
-
-       /* get the fieldinfo */
-       if (!(c = resolve_classref_eager(cr)))  {
-               return false;
-       }
+       uint32_t*          pc = (uint32_t*)          pr->mpc;
+       constant_classref* cr = (constant_classref*) pr->ref;
 
-       /* patch back original code */
-       *((u4 *) ra) = mcode;
+       // Resolve the class.
+       classinfo* c = resolve_classref_eager(cr);
 
-       /* synchronize instruction cache */
-
-       md_icacheflush(ra, 4);
-
-       /* if we show NOPs, we have to skip them */
-       if (opt_shownops)
-               ra = ra +4;
-
-       /* patch super class index */
-       disp = -(c->index);
+       if (c == NULL)
+               return false;
 
-       *((s4*)(ra + 2*4)) |= (disp & 0x0000ffff);
+       // Patch super class index.
+       int32_t disp = -(c->index);
+       pc[2] |= (disp & 0x0000ffff);
 
        disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
+       pc[5] |= (disp & 0x0000ffff);
 
-       *((s4 *)(ra + 5*4)) |= (disp & 0x0000ffff);
+       // Synchronize instruction cache.
+       md_icacheflush(pc + 2, 4 * 4);
 
-       /* sync instruction cache */
-       md_icacheflush(ra, 6*4);
+       // Patch back the original code.
+       patcher_patch_code(pr);
 
        return true;
 }
@@ -424,51 +325,29 @@ bool patcher_checkcast_interface(patchref_t *pr)
 
 *******************************************************************************/
 
-bool patcher_instanceof_interface(patchref_t *pr)
+bool patcher_instanceof_interface(patchref_tpr)
 {
-       u1                *ra;
-       u4                 mcode;
-       constant_classref *cr;
-       classinfo         *c;
-       s4                 disp;
-
-       /* get stuff from the stack */
-
-       ra    = (u1 *)                pr->mpc;
-       mcode =                       pr->mcode;
-       cr    = (constant_classref *) pr->ref;
+       uint32_t*          pc = (uint32_t*)          pr->mpc;
+       constant_classref* cr = (constant_classref*) pr->ref;
 
-       /* get the fieldinfo */
+       // Resolve the class.
+       classinfo* c = resolve_classref_eager(cr);
 
-       if (!(c = resolve_classref_eager(cr)))
+       if (c == NULL)
                return false;
 
-       /* patch back original code */
-
-       *((u4 *) ra) = mcode;
-
-       /* synchronize instruction cache */
-
-       md_icacheflush(ra, 4);
-
-       /* if we show disassembly, we have to skip the nop */
-
-       if (opt_shownops)
-               ra = ra + 4;
-
-       /* patch super class index */
-
-       disp = -(c->index);
-
-       *((s4 *) (ra + 2 * 4)) |= (disp & 0x0000ffff);
+       // Patch super class index.
+       int32_t disp = -(c->index);
+       pc[2] |= (disp & 0x0000ffff);
 
        disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
+       pc[4] |= (disp & 0x0000ffff);
 
-       *((s4 *) (ra + 4 * 4)) |= (disp & 0x0000ffff);
-
-       /* synchronize instruction cache */
+       // Synchronize instruction cache.
+       md_icacheflush(pc + 2, 3 * 4);
 
-       md_icacheflush(ra, 5 * 4);
+       // Patch back the original code.
+       patcher_patch_code(pr);
 
        return true;
 }
@@ -505,41 +384,26 @@ bool patcher_instanceof_interface(patchref_t *pr)
 
 *******************************************************************************/
 
-bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
+bool patcher_resolve_classref_to_classinfo(patchref_tpr)
 {
-       constant_classref *cr;
-       u1                *datap, *ra;
-       u4                 mcode;
-       classinfo         *c;
+       constant_classref* cr    = (constant_classref*) pr->ref;
+       uintptr_t*         datap = (uintptr_t*)         pr->datap;
 
-       /* get stuff from the stack */
+       // Resolve the class.
+       classinfo* c = resolve_classref_eager(cr);
 
-       ra    = (u1 *)                pr->mpc;
-       mcode =                       pr->mcode;
-       cr    = (constant_classref *) pr->ref;
-       datap = (u1 *)                pr->datap;
-
-       /* get the classinfo */
-
-       if (!(c = resolve_classref_eager(cr)))
+       if (c == NULL)
                return false;
 
-       /* patch back original code */
-
-       *((u4 *) ra) = mcode;
-
-       /* synchronize instruction cache */
-
-       md_icacheflush(ra, 4);
-
-       /* patch the classinfo pointer */
-
-       *((ptrint *) datap) = (ptrint) c;
-
-       /* synchronize data cache */
+       // Patch the classinfo pointer.
+       *datap = (uintptr_t) c;
 
+       // Synchronize data cache.
        md_dcacheflush(datap, SIZEOF_VOID_P);
 
+       // Patch back the original code.
+       patcher_patch_code(pr);
+
        return true;
 }
 
@@ -562,41 +426,26 @@ bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
 
 *******************************************************************************/
 
-bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
+bool patcher_resolve_classref_to_vftbl(patchref_tpr)
 {
-       constant_classref *cr;
-       u1                *datap, *ra;
-       u4                 mcode;
-       classinfo         *c;
+       constant_classref* cr    = (constant_classref*) pr->ref;
+       uintptr_t*         datap = (uintptr_t*)         pr->datap;
 
-       /* get stuff from the stack */
+       // Resolve the class.
+       classinfo* c = resolve_classref_eager(cr);
 
-       ra    = (u1 *)                pr->mpc;
-       mcode =                       pr->mcode;
-       cr    = (constant_classref *) pr->ref;
-       datap = (u1 *)                pr->datap;
-
-       /* get the fieldinfo */
-
-       if (!(c = resolve_classref_eager(cr)))
+       if (c == NULL)
                return false;
 
-       /* patch back original code */
-
-       *((u4 *) ra) = mcode;
-
-       /* synchronize instruction cache */
-
-       md_icacheflush(ra, 4);
-
-       /* patch super class' vftbl */
-
-       *((ptrint *) datap) = (ptrint) c->vftbl;
-
-       /* synchronize data cache */
+       // Patch super class' vftbl.
+       *datap = (uintptr_t) c->vftbl;
 
+       // Synchronize data cache.
        md_dcacheflush(datap, SIZEOF_VOID_P);
 
+       // Patch back the original code.
+       patcher_patch_code(pr);
+
        return true;
 }
 
@@ -609,41 +458,26 @@ bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
 
 *******************************************************************************/
 
-bool patcher_resolve_classref_to_flags(patchref_t *pr)
+bool patcher_resolve_classref_to_flags(patchref_tpr)
 {
-       constant_classref *cr;
-       u1                *datap, *ra;
-       u4                 mcode;
-       classinfo         *c;
+       constant_classref* cr    = (constant_classref*) pr->ref;
+       int32_t*           datap = (int32_t*)           pr->datap;
 
-       /* get stuff from the stack */
+       // Resolve the class.
+       classinfo* c = resolve_classref_eager(cr);
 
-       ra    = (u1 *)                pr->mpc;
-       mcode =                       pr->mcode;
-       cr    = (constant_classref *) pr->ref;
-       datap = (u1 *)                pr->datap;
-
-       /* get the fieldinfo */
-
-       if (!(c = resolve_classref_eager(cr)))
+       if (c == NULL)
                return false;
 
-       /* patch back original code */
-
-       *((u4 *) ra) = mcode;
-
-       /* synchronize instruction cache */
-
-       md_icacheflush(ra, 4);
-
-       /* patch class flags */
-
-       *((s4 *) datap) = (s4) c->flags;
-
-       /* synchronize data cache */
+       // Patch class flags.
+       *datap = (int32_t) c->flags;
 
+       // Synchronize data cache.
        md_dcacheflush(datap, SIZEOF_VOID_P);
 
+       // Patch back the original code.
+       patcher_patch_code(pr);
+
        return true;
 }
 
index 025c11f62e1e7207e72b2a76e2089f8bef7c9965..32fb401e2e8b3d18d43764b3dc886aeeca34e8c5 100644 (file)
 
 #include "vm/global.h"
 #include "vm/jit/python.h"
-#include "vm/jit/show.h"
+#include "vm/jit/show.hpp"
 #if defined(ENABLE_THREADS)
-# include "threads/lock-common.h"
+# include "threads/mutex.hpp"
 #endif
 
 #if defined(ENABLE_THREADS)
-static java_object_t *python_global_lock;
+static Mutex *python_global_mutex;
 #endif
 
 /*
@@ -1825,8 +1825,7 @@ void pythonpass_init() {
        }
 
 #if defined(ENABLE_THREADS)
-       python_global_lock = NEW(java_object_t);
-       LOCK_INIT_OBJECT_LOCK(python_global_lock);
+       python_global_mutex = Mutex_new();
 #endif
 
 }
@@ -1847,7 +1846,7 @@ int pythonpass_run(jitdata *jd, const char *module, const char *function) {
        int success = 0;
        root_state root;
 
-       LOCK_MONITOR_ENTER(python_global_lock);
+       Mutex_lock(python_global_mutex);
 
        pymodname = PyString_FromString(module);
        pymod = PyImport_Import(pymodname);
@@ -1888,7 +1887,7 @@ int pythonpass_run(jitdata *jd, const char *module, const char *function) {
        Py_XDECREF(pyret);
        Py_XDECREF(objcache);
 
-       LOCK_MONITOR_EXIT(python_global_lock);
+       Mutex_unlock(python_global_mutex);
 
        return (success == 1 ? 1 : 0);
 }
index 56a44d4294751dac3ba81bd1636fc663a4dcea8d..5d63784134e088fbb85f8b99120d5d29cc60bf47 100644 (file)
@@ -26,7 +26,7 @@
 #define _VM_JIT_PYTHON_H
 #if defined(ENABLE_PYTHON)
 
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
 
 void pythonpass_init();
 void pythonpass_cleanup();
index 699b362befc08de266cbc692e4cc69d680791719..3829d98651bcb3169a3434c88c365f9a35ed9cf6 100644 (file)
@@ -119,7 +119,7 @@ void reg_setup(jitdata *jd)
        assert(rd->tmpadrreguse == ADR_TMP_CNT);
        assert(rd->argadrreguse == ADR_ARG_CNT);
 #endif
-               
+
        /* setup the float register table */
 
        rd->tmpfltregs = DMNEW(s4, FLT_TMP_CNT);
@@ -148,11 +148,7 @@ void reg_setup(jitdata *jd)
        assert(rd->savfltreguse == FLT_SAV_CNT);
        assert(rd->tmpfltreguse == FLT_TMP_CNT);
 
-
        rd->freemem    = DMNEW(s4, m->maxstack);
-#if defined(HAS_4BYTE_STACKSLOT)
-       rd->freemem_2  = DMNEW(s4, m->maxstack);
-#endif
 
 #if defined(SPECIALMEMUSE)
 # if defined(__DARWIN__)
index b4196b1f4477200aa59f08b2af57e931875f0a3a..9dc637b3f12df8b3d866bc2f2a315cdb509f4d60 100644 (file)
@@ -37,7 +37,7 @@ typedef struct registerdata registerdata;
 
 #include "arch.h"
 
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
 #include "vm/jit/verify/typeinfo.h"
 
 
@@ -99,10 +99,6 @@ struct registerdata {
        int freeargadrtop;              /* free argument address register count   */
 #endif
 
-#if defined(HAS_4BYTE_STACKSLOT)
-       int *freemem_2;
-       int freememtop_2;
-#endif
        int *freemem;                   /* free scratch memory                    */
        int freememtop;                 /* free memory count                      */
 
@@ -133,8 +129,16 @@ struct registerdata {
 
 /* function prototypes ********************************************************/
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 void reg_setup(jitdata *jd);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* _REG_H */
 
 
diff --git a/src/vm/jit/replace.c b/src/vm/jit/replace.c
deleted file mode 100644 (file)
index dea13b1..0000000
+++ /dev/null
@@ -1,3609 +0,0 @@
-/* src/vm/jit/replace.c - on-stack replacement of 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.
-
-*/
-
-#include "config.h"
-#include "vm/types.h"
-
-#include <assert.h>
-#include <stdint.h>
-#include <stdlib.h>
-
-#include "arch.h"
-#include "md.h"
-
-#if defined(ENABLE_GC_CACAO)
-# include "mm/cacao-gc/gc.h"
-#endif
-
-#include "mm/memory.h"
-
-#include "threads/thread.hpp"
-
-#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/executionstate.h"
-#include "vm/jit/jit.h"
-#include "vm/jit/methodheader.h"
-#include "vm/jit/replace.h"
-#include "vm/jit/show.h"
-#include "vm/jit/stack.h"
-
-
-#define REPLACE_PATCH_DYNAMIC_CALL
-/*#define REPLACE_PATCH_ALL*/
-
-#if defined(ENABLE_VMLOG)
-#include <vmlog_cacao.h>
-#endif
-
-/*** architecture-dependent configuration *************************************/
-
-/* first unset the macros (default) */
-#undef REPLACE_RA_BETWEEN_FRAMES
-#undef REPLACE_RA_TOP_OF_FRAME
-#undef REPLACE_RA_LINKAGE_AREA
-#undef REPLACE_LEAFMETHODS_RA_REGISTER
-
-/* i386, x86_64 and m68k */
-#if defined(__I386__) || defined(__X86_64__) || defined(__M68K__)
-#define REPLACE_RA_BETWEEN_FRAMES
-/* alpha */
-#elif defined(__ALPHA__)
-#define REPLACE_RA_TOP_OF_FRAME
-#define REPLACE_LEAFMETHODS_RA_REGISTER
-/* powerpc */
-#elif defined(__POWERPC__)
-#define REPLACE_RA_LINKAGE_AREA
-#define REPLACE_LEAFMETHODS_RA_REGISTER
-/* s390 */
-#elif defined(__S390__)
-#define REPLACE_RA_TOP_OF_FRAME
-#endif
-
-
-/*** configuration of native stack slot size **********************************/
-
-/* XXX this should be in md-abi.h files, probably */
-
-#if defined(HAS_4BYTE_STACKSLOT)
-#define SIZE_OF_STACKSLOT      4
-#define STACK_SLOTS_PER_FLOAT  2
-typedef u4 stackslot_t;
-#else
-#define SIZE_OF_STACKSLOT      8
-#define STACK_SLOTS_PER_FLOAT  1
-typedef u8 stackslot_t;
-#endif
-
-
-/*** debugging ****************************************************************/
-
-#if !defined(NDEBUG)
-static void java_value_print(s4 type, replace_val_t value);
-static void replace_stackframeinfo_println(stackframeinfo_t *sfi);
-#endif
-
-#if !defined(NDEBUG)
-#define DOLOG(code)        do{ if (opt_TraceReplacement > 1) { code; } } while(0)
-#define DOLOG_SHORT(code)  do{ if (opt_TraceReplacement > 0) { code; } } while(0)
-#else
-#define DOLOG(code)
-#define DOLOG_SHORT(code)
-#endif
-
-
-/*** statistics ***************************************************************/
-
-#define REPLACE_STATISTICS
-
-#if defined(REPLACE_STATISTICS)
-
-static int stat_replacements = 0;
-static int stat_frames = 0;
-static int stat_recompile = 0;
-static int stat_staticpatch = 0;
-static int stat_unroll_inline = 0;
-static int stat_unroll_call = 0;
-static int stat_dist_frames[20] = { 0 };
-static int stat_dist_locals[20] = { 0 };
-static int stat_dist_locals_adr[10] = { 0 };
-static int stat_dist_locals_prim[10] = { 0 };
-static int stat_dist_locals_ret[10] = { 0 };
-static int stat_dist_locals_void[10] = { 0 };
-static int stat_dist_stack[10] = { 0 };
-static int stat_dist_stack_adr[10] = { 0 };
-static int stat_dist_stack_prim[10] = { 0 };
-static int stat_dist_stack_ret[10] = { 0 };
-static int stat_methods = 0;
-static int stat_rploints = 0;
-static int stat_regallocs = 0;
-static int stat_dist_method_rplpoints[20] = { 0 };
-
-#define REPLACE_COUNT(cnt)  (cnt)++
-#define REPLACE_COUNT_IF(cnt, cond)  do{ if(cond) (cnt)++; } while(0)
-#define REPLACE_COUNT_INC(cnt, inc)  ((cnt) += (inc))
-
-#define REPLACE_COUNT_DIST(array, val)                               \
-    do {                                                             \
-        int limit = (sizeof(array) / sizeof(int)) - 1;               \
-        if ((val) < (limit)) (array)[val]++;                         \
-        else (array)[limit]++;                                       \
-    } while (0)
-
-static void replace_statistics_source_frame(sourceframe_t *frame);
-
-#else
-
-#define REPLACE_COUNT(cnt)
-#define REPLACE_COUNT_IF(cnt, cond)
-#define REPLACE_COUNT_INC(cnt, inc)
-#define REPLACE_COUNT_DIST(array, val)
-
-#endif /* defined(REPLACE_STATISTICS) */
-
-
-/*** constants used internally ************************************************/
-
-#define TOP_IS_NORMAL    0
-#define TOP_IS_ON_STACK  1
-#define TOP_IS_IN_ITMP1  2
-#define TOP_IS_VOID      3
-
-
-/******************************************************************************/
-/* PART I: Creating / freeing replacement points                              */
-/******************************************************************************/
-
-
-/* replace_create_replacement_point ********************************************
-   Create a replacement point.
-  
-   IN:
-       jd...............current jitdata
-          iinfo............inlining info for the current position
-          rp...............pre-allocated (uninitialized) rplpoint
-          type.............RPLPOINT_TYPE constant
-          iptr.............current instruction
-          *pra.............current rplalloc pointer
-          javalocals.......the javalocals at the current point
-          stackvars........the stack variables at the current point
-          stackdepth.......the stack depth at the current point
-          paramcount.......number of parameters at the start of stackvars
-  
-   OUT:
-       *rpa.............points to the next free rplalloc
-  
-*******************************************************************************/
-
-static void replace_create_replacement_point(jitdata *jd,
-                                                                                        insinfo_inline *iinfo,
-                                                                                        rplpoint *rp,
-                                                                                        s4 type,
-                                                                                        instruction *iptr,
-                                                                                        rplalloc **pra,
-                                                                                        s4 *javalocals,
-                                                                                        s4 *stackvars,
-                                                                                        s4 stackdepth,
-                                                                                        s4 paramcount)
-{
-       rplalloc *ra;
-       s4        i;
-       varinfo  *v;
-       s4        index;
-
-       ra = *pra;
-
-       REPLACE_COUNT(stat_rploints);
-
-       rp->method = (iinfo) ? iinfo->method : jd->m;
-       rp->pc = NULL;        /* set by codegen */
-       rp->callsize = 0;     /* set by codegen */
-       rp->regalloc = ra;
-       rp->flags = 0;
-       rp->type = type;
-       rp->id = iptr->flags.bits >> INS_FLAG_ID_SHIFT;
-
-       /* XXX unify these two fields */
-       rp->parent = (iinfo) ? iinfo->rp : NULL;
-
-       /* store local allocation info of javalocals */
-
-       if (javalocals) {
-               for (i = 0; i < rp->method->maxlocals; ++i) {
-                       index = javalocals[i];
-                       if (index == UNUSED)
-                               continue;
-
-                       ra->index = i;
-                       if (index >= 0) {
-                               v = VAR(index);
-                               ra->flags = v->flags & (INMEMORY);
-                               ra->regoff = v->vv.regoff;
-                               ra->type = v->type;
-                       }
-                       else {
-                               ra->regoff = RETADDR_FROM_JAVALOCAL(index);
-                               ra->type = TYPE_RET;
-                               ra->flags = 0;
-                       }
-                       ra++;
-               }
-       }
-
-       /* store allocation info of java stack vars */
-
-       for (i = 0; i < stackdepth; ++i) {
-               v = VAR(stackvars[i]);
-               ra->flags = v->flags & (INMEMORY);
-               ra->index = (i < paramcount) ? RPLALLOC_PARAM : RPLALLOC_STACK;
-               ra->type  = v->type;
-               /* XXX how to handle locals on the stack containing returnAddresses? */
-               if (v->type == TYPE_RET) {
-                       assert(stackvars[i] >= jd->localcount);
-                       ra->regoff = v->vv.retaddr->nr;
-               }
-               else
-                       ra->regoff = v->vv.regoff;
-               ra++;
-       }
-
-       /* total number of allocations */
-
-       rp->regalloccount = ra - rp->regalloc;
-
-       *pra = ra;
-}
-
-
-/* replace_create_inline_start_replacement_point *******************************
-
-   Create an INLINE_START replacement point.
-
-   IN:
-       jd...............current jitdata
-          rp...............pre-allocated (uninitialized) rplpoint
-          iptr.............current instruction
-          *pra.............current rplalloc pointer
-          javalocals.......the javalocals at the current point
-
-   OUT:
-       *rpa.............points to the next free rplalloc
-
-   RETURN VALUE:
-       the insinfo_inline * for the following inlined body
-
-*******************************************************************************/
-
-static insinfo_inline * replace_create_inline_start_replacement_point(
-                                                                                        jitdata *jd,
-                                                                                        rplpoint *rp,
-                                                                                        instruction *iptr,
-                                                                                        rplalloc **pra,
-                                                                                        s4 *javalocals)
-{
-       insinfo_inline *calleeinfo;
-       rplalloc       *ra;
-
-       calleeinfo = iptr->sx.s23.s3.inlineinfo;
-
-       calleeinfo->rp = rp;
-
-       replace_create_replacement_point(jd, calleeinfo->parent, rp,
-                       RPLPOINT_TYPE_INLINE, iptr, pra,
-                       javalocals,
-                       calleeinfo->stackvars, calleeinfo->stackvarscount,
-                       calleeinfo->paramcount);
-
-       if (calleeinfo->synclocal != UNUSED) {
-               ra = (*pra)++;
-               ra->index  = RPLALLOC_SYNC;
-               ra->regoff = jd->var[calleeinfo->synclocal].vv.regoff;
-               ra->flags  = jd->var[calleeinfo->synclocal].flags & INMEMORY;
-               ra->type   = TYPE_ADR;
-
-               rp->regalloccount++;
-       }
-
-       return calleeinfo;
-}
-
-
-/* replace_create_replacement_points *******************************************
-   Create the replacement points for the given code.
-  
-   IN:
-       jd...............current jitdata, must not have any replacement points
-  
-   OUT:
-       code->rplpoints.......set to the list of replacement points
-          code->rplpointcount...number of replacement points
-          code->regalloc........list of allocation info
-          code->regalloccount...total length of allocation info list
-          code->globalcount.....number of global allocations at the
-                                start of code->regalloc
-  
-   RETURN VALUE:
-       true.............everything ok 
-       false............an exception has been thrown
-   
-*******************************************************************************/
-
-#define CLEAR_javalocals(array, method)                              \
-    do {                                                             \
-        for (i=0; i<(method)->maxlocals; ++i)                        \
-            (array)[i] = UNUSED;                                     \
-    } while (0)
-
-#define COPY_OR_CLEAR_javalocals(dest, array, method)                \
-    do {                                                             \
-        if ((array) != NULL)                                         \
-            MCOPY((dest), (array), s4, (method)->maxlocals);         \
-        else                                                         \
-            CLEAR_javalocals((dest), (method));                      \
-    } while (0)
-
-#define COUNT_javalocals(array, method, counter)                     \
-    do {                                                             \
-        for (i=0; i<(method)->maxlocals; ++i)                        \
-            if ((array)[i] != UNUSED)                                \
-                               (counter)++;                                         \
-    } while (0)
-
-bool replace_create_replacement_points(jitdata *jd)
-{
-       codeinfo        *code;
-       registerdata    *rd;
-       basicblock      *bptr;
-       int              count;
-       methodinfo      *m;
-       rplpoint        *rplpoints;
-       rplpoint        *rp;
-       int              alloccount;
-       rplalloc        *regalloc;
-       rplalloc        *ra;
-       int              i;
-       instruction     *iptr;
-       instruction     *iend;
-       s4              *javalocals;
-       s4              *jl;
-       methoddesc      *md;
-       insinfo_inline  *iinfo;
-       s4               startcount;
-       s4               firstcount;
-#if defined(REPLACE_PATCH_DYNAMIC_CALL)
-       bool             needentry;
-#endif
-
-       REPLACE_COUNT(stat_methods);
-
-       /* get required compiler data */
-
-       code = jd->code;
-       rd   = jd->rd;
-
-       /* assert that we wont overwrite already allocated data */
-
-       assert(code);
-       assert(code->m);
-       assert(code->rplpoints == NULL);
-       assert(code->rplpointcount == 0);
-       assert(code->regalloc == NULL);
-       assert(code->regalloccount == 0);
-       assert(code->globalcount == 0);
-
-       m = code->m;
-
-       /* in instance methods, we may need a rplpoint at the method entry */
-
-#if defined(REPLACE_PATCH_DYNAMIC_CALL)
-       if (!(m->flags & ACC_STATIC)) {
-               jd->basicblocks[0].bitflags |= BBFLAG_REPLACEMENT;
-               needentry = true;
-       }
-       else {
-               needentry = false;
-       }
-#endif /* defined(REPLACE_PATCH_DYNAMIC_CALL) */
-
-       /* iterate over the basic block list to find replacement points */
-
-       count = 0;
-       alloccount = 0;
-
-       javalocals = DMNEW(s4, jd->maxlocals);
-
-       for (bptr = jd->basicblocks; bptr; bptr = bptr->next) {
-
-               /* skip dead code */
-
-               if (bptr->flags < BBFINISHED)
-                       continue;
-
-               /* get info about this block */
-
-               m = bptr->method;
-               iinfo = bptr->inlineinfo;
-
-               /* initialize javalocals at the start of this block */
-
-               COPY_OR_CLEAR_javalocals(javalocals, bptr->javalocals, m);
-
-               /* iterate over the instructions */
-
-               iptr = bptr->iinstr;
-               iend = iptr + bptr->icount;
-               startcount = count;
-               firstcount = count;
-
-               for (; iptr != iend; ++iptr) {
-                       switch (iptr->opc) {
-#if defined(ENABLE_GC_CACAO)
-                               case ICMD_BUILTIN:
-                                       md = iptr->sx.s23.s3.bte->md;
-                                       count++;
-                                       COUNT_javalocals(javalocals, m, alloccount);
-                                       alloccount += iptr->s1.argcount;
-                                       if (iinfo)
-                                               alloccount -= iinfo->throughcount;
-                                       break;
-#endif
-
-                               case ICMD_INVOKESTATIC:
-                               case ICMD_INVOKESPECIAL:
-                               case ICMD_INVOKEVIRTUAL:
-                               case ICMD_INVOKEINTERFACE:
-                                       INSTRUCTION_GET_METHODDESC(iptr, md);
-                                       count++;
-                                       COUNT_javalocals(javalocals, m, alloccount);
-                                       alloccount += iptr->s1.argcount;
-                                       if (iinfo)
-                                               alloccount -= iinfo->throughcount;
-                                       break;
-
-                               case ICMD_ISTORE:
-                               case ICMD_LSTORE:
-                               case ICMD_FSTORE:
-                               case ICMD_DSTORE:
-                               case ICMD_ASTORE:
-                                       stack_javalocals_store(iptr, javalocals);
-                                       break;
-
-                               case ICMD_IRETURN:
-                               case ICMD_LRETURN:
-                               case ICMD_FRETURN:
-                               case ICMD_DRETURN:
-                               case ICMD_ARETURN:
-                                       alloccount += 1;
-                                       /* FALLTHROUGH! */
-                               case ICMD_RETURN:
-                                       count++;
-                                       break;
-
-                               case ICMD_INLINE_START:
-                                       iinfo = iptr->sx.s23.s3.inlineinfo;
-
-                                       count++;
-                                       COUNT_javalocals(javalocals, m, alloccount);
-                                       alloccount += iinfo->stackvarscount;
-                                       if (iinfo->synclocal != UNUSED)
-                                               alloccount++;
-
-                                       m = iinfo->method;
-                                       /* javalocals may be set at next block start, or now */
-                                       COPY_OR_CLEAR_javalocals(javalocals, iinfo->javalocals_start, m);
-                                       break;
-
-                               case ICMD_INLINE_BODY:
-                                       assert(iinfo == iptr->sx.s23.s3.inlineinfo);
-
-                                       jl = iinfo->javalocals_start;
-                                       if (jl == NULL) {
-                                               /* get the javalocals from the following block start */
-                                               assert(bptr->next);
-                                               jl = bptr->next->javalocals;
-                                       }
-                                       count++;
-                                       COUNT_javalocals(jl, m, alloccount);
-                                       break;
-
-                               case ICMD_INLINE_END:
-                                       assert(iinfo == iptr->sx.s23.s3.inlineinfo ||
-                                                  iinfo == iptr->sx.s23.s3.inlineinfo->parent);
-                                       iinfo = iptr->sx.s23.s3.inlineinfo;
-                                       m = iinfo->outer;
-                                       if (iinfo->javalocals_end)
-                                               MCOPY(javalocals, iinfo->javalocals_end, s4, m->maxlocals);
-                                       iinfo = iinfo->parent;
-                                       break;
-                       }
-
-                       if (iptr == bptr->iinstr)
-                               firstcount = count;
-               } /* end instruction loop */
-
-               /* create replacement points at targets of backward branches */
-               /* We only need the replacement point there, if there is no  */
-               /* replacement point inside the block.                       */
-
-               if (bptr->bitflags & BBFLAG_REPLACEMENT) {
-#if defined(REPLACE_PATCH_DYNAMIC_CALL)
-                       int test = (needentry && bptr == jd->basicblocks) ? firstcount : count;
-#else
-                       int test = count;
-#endif
-                       if (test > startcount) {
-                               /* we don't need an extra rplpoint */
-                               bptr->bitflags &= ~BBFLAG_REPLACEMENT;
-                       }
-                       else {
-                               count++;
-                               alloccount += bptr->indepth;
-                               if (bptr->inlineinfo)
-                                       alloccount -= bptr->inlineinfo->throughcount;
-
-                               COUNT_javalocals(bptr->javalocals, bptr->method, alloccount);
-                       }
-               }
-
-       } /* end basicblock loop */
-
-       /* if no points were found, there's nothing to do */
-
-       if (!count)
-               return true;
-
-       /* allocate replacement point array and allocation array */
-
-       rplpoints = MNEW(rplpoint, count);
-       regalloc = MNEW(rplalloc, alloccount);
-       ra = regalloc;
-
-       /* initialize replacement point structs */
-
-       rp = rplpoints;
-
-       /* XXX try to share code with the counting loop! */
-
-       for (bptr = jd->basicblocks; bptr; bptr = bptr->next) {
-               /* skip dead code */
-
-               if (bptr->flags < BBFINISHED)
-                       continue;
-
-               /* get info about this block */
-
-               m = bptr->method;
-               iinfo = bptr->inlineinfo;
-
-               /* initialize javalocals at the start of this block */
-
-               COPY_OR_CLEAR_javalocals(javalocals, bptr->javalocals, m);
-
-               /* create replacement points at targets of backward branches */
-
-               if (bptr->bitflags & BBFLAG_REPLACEMENT) {
-
-                       i = (iinfo) ? iinfo->throughcount : 0;
-                       replace_create_replacement_point(jd, iinfo, rp++,
-                                       bptr->type, bptr->iinstr, &ra,
-                                       bptr->javalocals, bptr->invars + i, bptr->indepth - i, 0);
-
-                       if (JITDATA_HAS_FLAG_COUNTDOWN(jd))
-                               rp[-1].flags |= RPLPOINT_FLAG_COUNTDOWN;
-               }
-
-               /* iterate over the instructions */
-
-               iptr = bptr->iinstr;
-               iend = iptr + bptr->icount;
-
-               for (; iptr != iend; ++iptr) {
-                       switch (iptr->opc) {
-#if defined(ENABLE_GC_CACAO)
-                               case ICMD_BUILTIN:
-                                       md = iptr->sx.s23.s3.bte->md;
-
-                                       i = (iinfo) ? iinfo->throughcount : 0;
-                                       replace_create_replacement_point(jd, iinfo, rp++,
-                                                       RPLPOINT_TYPE_CALL, iptr, &ra,
-                                                       javalocals, iptr->sx.s23.s2.args,
-                                                       iptr->s1.argcount - i,
-                                                       md->paramcount);
-                                       break;
-#endif
-
-                               case ICMD_INVOKESTATIC:
-                               case ICMD_INVOKESPECIAL:
-                               case ICMD_INVOKEVIRTUAL:
-                               case ICMD_INVOKEINTERFACE:
-                                       INSTRUCTION_GET_METHODDESC(iptr, md);
-
-                                       i = (iinfo) ? iinfo->throughcount : 0;
-                                       replace_create_replacement_point(jd, iinfo, rp++,
-                                                       RPLPOINT_TYPE_CALL, iptr, &ra,
-                                                       javalocals, iptr->sx.s23.s2.args,
-                                                       iptr->s1.argcount - i,
-                                                       md->paramcount);
-                                       break;
-
-                               case ICMD_ISTORE:
-                               case ICMD_LSTORE:
-                               case ICMD_FSTORE:
-                               case ICMD_DSTORE:
-                               case ICMD_ASTORE:
-                                       stack_javalocals_store(iptr, javalocals);
-                                       break;
-
-                               case ICMD_IRETURN:
-                               case ICMD_LRETURN:
-                               case ICMD_FRETURN:
-                               case ICMD_DRETURN:
-                               case ICMD_ARETURN:
-                                       replace_create_replacement_point(jd, iinfo, rp++,
-                                                       RPLPOINT_TYPE_RETURN, iptr, &ra,
-                                                       NULL, &(iptr->s1.varindex), 1, 0);
-                                       break;
-
-                               case ICMD_RETURN:
-                                       replace_create_replacement_point(jd, iinfo, rp++,
-                                                       RPLPOINT_TYPE_RETURN, iptr, &ra,
-                                                       NULL, NULL, 0, 0);
-                                       break;
-
-                               case ICMD_INLINE_START:
-                                       iinfo = replace_create_inline_start_replacement_point(
-                                                               jd, rp++, iptr, &ra, javalocals);
-                                       m = iinfo->method;
-                                       /* javalocals may be set at next block start, or now */
-                                       COPY_OR_CLEAR_javalocals(javalocals, iinfo->javalocals_start, m);
-                                       break;
-
-                               case ICMD_INLINE_BODY:
-                                       assert(iinfo == iptr->sx.s23.s3.inlineinfo);
-
-                                       jl = iinfo->javalocals_start;
-                                       if (jl == NULL) {
-                                               /* get the javalocals from the following block start */
-                                               assert(bptr->next);
-                                               jl = bptr->next->javalocals;
-                                       }
-                                       /* create a non-trappable rplpoint */
-                                       replace_create_replacement_point(jd, iinfo, rp++,
-                                                       RPLPOINT_TYPE_BODY, iptr, &ra,
-                                                       jl, NULL, 0, 0);
-                                       rp[-1].flags |= RPLPOINT_FLAG_NOTRAP;
-                                       break;
-
-                               case ICMD_INLINE_END:
-                                       assert(iinfo == iptr->sx.s23.s3.inlineinfo ||
-                                                  iinfo == iptr->sx.s23.s3.inlineinfo->parent);
-                                       iinfo = iptr->sx.s23.s3.inlineinfo;
-                                       m = iinfo->outer;
-                                       if (iinfo->javalocals_end)
-                                               MCOPY(javalocals, iinfo->javalocals_end, s4, m->maxlocals);
-                                       iinfo = iinfo->parent;
-                                       break;
-                       }
-               } /* end instruction loop */
-       } /* end basicblock loop */
-
-       assert((rp - rplpoints) == count);
-       assert((ra - regalloc) == alloccount);
-
-       /* store the data in the codeinfo */
-
-       code->rplpoints     = rplpoints;
-       code->rplpointcount = count;
-       code->regalloc      = regalloc;
-       code->regalloccount = alloccount;
-       code->globalcount   = 0;
-       code->savedintcount = INT_SAV_CNT - rd->savintreguse;
-       code->savedfltcount = FLT_SAV_CNT - rd->savfltreguse;
-#if defined(HAS_ADDRESS_REGISTER_FILE)
-       code->savedadrcount = ADR_SAV_CNT - rd->savadrreguse;
-#endif
-       code->memuse        = rd->memuse;
-       code->stackframesize = jd->cd->stackframesize;
-
-       REPLACE_COUNT_DIST(stat_dist_method_rplpoints, count);
-       REPLACE_COUNT_INC(stat_regallocs, alloccount);
-
-       /* everything alright */
-
-       return true;
-}
-
-
-/* replace_free_replacement_points *********************************************
-   Free memory used by replacement points.
-  
-   IN:
-       code.............codeinfo whose replacement points should be freed.
-  
-*******************************************************************************/
-
-void replace_free_replacement_points(codeinfo *code)
-{
-       assert(code);
-
-       if (code->rplpoints)
-               MFREE(code->rplpoints,rplpoint,code->rplpointcount);
-
-       if (code->regalloc)
-               MFREE(code->regalloc,rplalloc,code->regalloccount);
-
-       code->rplpoints = NULL;
-       code->rplpointcount = 0;
-       code->regalloc = NULL;
-       code->regalloccount = 0;
-       code->globalcount = 0;
-}
-
-
-/******************************************************************************/
-/* PART II: Activating / deactivating replacement points                      */
-/******************************************************************************/
-
-
-/* replace_activate_replacement_points *****************************************
-   Activate the replacement points of the given compilation unit. When this
-   function returns, the replacement points are "armed", so each thread
-   reaching one of the points will enter the replacement mechanism.
-   
-   IN:
-       code.............codeinfo of which replacement points should be
-                                               activated
-          mappable.........if true, only mappable replacement points are
-                                               activated
-  
-*******************************************************************************/
-
-void replace_activate_replacement_points(codeinfo *code, bool mappable)
-{
-       rplpoint *rp;
-       s4        i;
-       s4        count;
-       u1       *savedmcode;
-
-       assert(code->savedmcode == NULL);
-
-       /* count trappable replacement points */
-
-       count = 0;
-       i = code->rplpointcount;
-       rp = code->rplpoints;
-       for (; i--; rp++) {
-               if (rp->flags & RPLPOINT_FLAG_NOTRAP)
-                       continue;
-
-               if (mappable && (rp->type == RPLPOINT_TYPE_RETURN))
-                       continue;
-
-               count++;
-       }
-
-       /* allocate buffer for saved machine code */
-
-       savedmcode = MNEW(u1, count * REPLACEMENT_PATCH_SIZE);
-       code->savedmcode = savedmcode;
-       savedmcode += count * REPLACEMENT_PATCH_SIZE;
-
-       /* activate trappable replacement points */
-       /* (in reverse order to handle overlapping points within basic blocks) */
-
-       i = code->rplpointcount;
-       rp = code->rplpoints + i;
-       while (rp--, i--) {
-               assert(!(rp->flags & RPLPOINT_FLAG_ACTIVE));
-
-               if (rp->flags & RPLPOINT_FLAG_NOTRAP)
-                       continue;
-
-               if (mappable && (rp->type == RPLPOINT_TYPE_RETURN))
-                       continue;
-
-               DOLOG( printf("activate replacement point:\n");
-                          replace_replacement_point_println(rp, 1); fflush(stdout); );
-
-               savedmcode -= REPLACEMENT_PATCH_SIZE;
-
-#if defined(ENABLE_JIT)
-# if defined(ENABLE_DISASSEMBLER)
-               DOLOG( printf("\tinstruction before: ");
-                          disassinstr(rp->pc); fflush(stdout); );
-# endif
-
-               md_patch_replacement_point(rp->pc, savedmcode, false);
-
-# if defined(ENABLE_DISASSEMBLER)
-               DOLOG( printf("\tinstruction after : ");
-                          disassinstr(rp->pc); fflush(stdout); );
-# endif
-#endif
-
-               rp->flags |= RPLPOINT_FLAG_ACTIVE;
-       }
-
-       assert(savedmcode == code->savedmcode);
-}
-
-
-/* replace_deactivate_replacement_points ***************************************
-   Deactivate a replacement points in the given compilation unit.
-   When this function returns, the replacement points will be "un-armed",
-   that is a each thread reaching a point will just continue normally.
-   
-   IN:
-       code.............the compilation unit
-  
-*******************************************************************************/
-
-void replace_deactivate_replacement_points(codeinfo *code)
-{
-       rplpoint *rp;
-       s4        i;
-       s4        count;
-       u1       *savedmcode;
-
-       if (code->savedmcode == NULL) {
-               /* disarm countdown points by patching the branches */
-
-               i = code->rplpointcount;
-               rp = code->rplpoints;
-               for (; i--; rp++) {
-                       if ((rp->flags & (RPLPOINT_FLAG_ACTIVE | RPLPOINT_FLAG_COUNTDOWN))
-                                       == RPLPOINT_FLAG_COUNTDOWN)
-                       {
-#if 0
-                               *(s4*) (rp->pc + 9) = 0; /* XXX machine dependent! */
-#endif
-                       }
-               }
-               return;
-       }
-
-       assert(code->savedmcode != NULL);
-       savedmcode = code->savedmcode;
-
-       /* de-activate each trappable replacement point */
-
-       i = code->rplpointcount;
-       rp = code->rplpoints;
-       count = 0;
-       for (; i--; rp++) {
-               if (!(rp->flags & RPLPOINT_FLAG_ACTIVE))
-                       continue;
-
-               count++;
-
-               DOLOG( printf("deactivate replacement point:\n");
-                          replace_replacement_point_println(rp, 1); fflush(stdout); );
-
-#if defined(ENABLE_JIT)
-# if defined(ENABLE_DISASSEMBLER)
-               DOLOG( printf("\tinstruction before: ");
-                          disassinstr(rp->pc); fflush(stdout); );
-# endif
-
-               md_patch_replacement_point(rp->pc, savedmcode, true);
-
-# if defined(ENABLE_DISASSEMBLER)
-               DOLOG( printf("\tinstruction before: ");
-                          disassinstr(rp->pc); fflush(stdout); );
-# endif
-#endif
-
-               rp->flags &= ~RPLPOINT_FLAG_ACTIVE;
-
-               savedmcode += REPLACEMENT_PATCH_SIZE;
-       }
-
-       assert(savedmcode == code->savedmcode + count * REPLACEMENT_PATCH_SIZE);
-
-       /* free saved machine code */
-
-       MFREE(code->savedmcode, u1, count * REPLACEMENT_PATCH_SIZE);
-       code->savedmcode = NULL;
-}
-
-
-/******************************************************************************/
-/* PART III: The replacement mechanism                                        */
-/******************************************************************************/
-
-
-/* replace_read_value **********************************************************
-
-   Read a value with the given allocation from the execution state.
-   
-   IN:
-          es...............execution state
-          ra...............allocation
-          javaval..........where to put the value
-
-   OUT:
-       *javaval.........the value
-  
-*******************************************************************************/
-
-static void replace_read_value(executionstate_t *es,
-                                                          rplalloc *ra,
-                                                          replace_val_t *javaval)
-{
-       if (ra->flags & INMEMORY) {
-               /* XXX HAS_4BYTE_STACKSLOT may not be the right discriminant here */
-#ifdef HAS_4BYTE_STACKSLOT
-               if (IS_2_WORD_TYPE(ra->type)) {
-                       javaval->l = *(u8*)(es->sp + ra->regoff);
-               }
-               else {
-#endif
-                       javaval->p = *(ptrint*)(es->sp + ra->regoff);
-#ifdef HAS_4BYTE_STACKSLOT
-               }
-#endif
-       }
-       else {
-               /* allocated register */
-               if (IS_FLT_DBL_TYPE(ra->type)) {
-                       javaval->d = es->fltregs[ra->regoff];
-
-                       if (ra->type == TYPE_FLT)
-                               javaval->f = javaval->d;
-               }
-#if defined(HAS_ADDRESS_REGISTER_FILE)
-               else if (IS_ADR_TYPE(ra->type)) {
-                       javaval->p = es->adrregs[ra->regoff];
-               }
-#endif
-               else {
-#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
-                       if (ra->type == TYPE_LNG) {
-                               javaval->words.lo = es->intregs[GET_LOW_REG(ra->regoff)];
-                               javaval->words.hi = es->intregs[GET_HIGH_REG(ra->regoff)];
-                       }
-                       else
-#endif /* defined(SUPPORT_COMBINE_INTEGER_REGISTERS) */
-                               javaval->p = es->intregs[ra->regoff];
-               }
-       }
-}
-
-
-/* replace_write_value *********************************************************
-
-   Write a value to the given allocation in the execution state.
-   
-   IN:
-          es...............execution state
-          ra...............allocation
-          *javaval.........the value
-
-*******************************************************************************/
-
-static void replace_write_value(executionstate_t *es,
-                                                           rplalloc *ra,
-                                                           replace_val_t *javaval)
-{
-       if (ra->flags & INMEMORY) {
-               /* XXX HAS_4BYTE_STACKSLOT may not be the right discriminant here */
-#ifdef HAS_4BYTE_STACKSLOT
-               if (IS_2_WORD_TYPE(ra->type)) {
-                       *(u8*)(es->sp + ra->regoff) = javaval->l;
-               }
-               else {
-#endif
-                       *(ptrint*)(es->sp + ra->regoff) = javaval->p;
-#ifdef HAS_4BYTE_STACKSLOT
-               }
-#endif
-       }
-       else {
-               /* allocated register */
-               switch (ra->type) {
-                       case TYPE_FLT:
-                               es->fltregs[ra->regoff] = (double) javaval->f;
-                               break;
-                       case TYPE_DBL:
-                               es->fltregs[ra->regoff] = javaval->d;
-                               break;
-#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
-                       case TYPE_LNG:
-                               es->intregs[GET_LOW_REG(ra->regoff)] = javaval->words.lo;
-                               es->intregs[GET_HIGH_REG(ra->regoff)] = javaval->words.hi;
-                               break;
-#endif
-#if defined(HAS_ADDRESS_REGISTER_FILE)
-                       case TYPE_ADR:
-                               es->adrregs[ra->regoff] = javaval->p;
-#endif
-                       default:
-                               es->intregs[ra->regoff] = javaval->p;
-               }
-       }
-}
-
-
-/* replace_new_sourceframe *****************************************************
-
-   Allocate a new source frame and insert it at the front of the frame list.
-   
-   IN:
-          ss...............the source state
-
-   OUT:
-          ss->frames.......set to new frame (the new head of the frame list).
-
-   RETURN VALUE:
-       returns the new frame
-
-*******************************************************************************/
-
-static sourceframe_t *replace_new_sourceframe(sourcestate_t *ss)
-{
-       sourceframe_t *frame;
-
-       frame = DNEW(sourceframe_t);
-       MZERO(frame, sourceframe_t, 1);
-
-       frame->down = ss->frames;
-       ss->frames = frame;
-
-       return frame;
-}
-
-
-/* replace_read_executionstate *************************************************
-
-   Read a source frame from the given executions state.
-   The new source frame is pushed to the front of the frame list of the
-   source state.
-
-   IN:
-       rp...............replacement point at which `es` was taken
-          es...............execution state
-          ss...............the source state to add the source frame to
-          topframe.........true, if the first (top-most) source frame on the
-                           stack is to be read
-
-   OUT:
-       *ss..............the source state with the newly created source frame
-                           added
-  
-*******************************************************************************/
-
-static s4 replace_normalize_type_map[] = {
-/* RPLPOINT_TYPE_STD    |--> */ RPLPOINT_TYPE_STD,
-/* RPLPOINT_TYPE_EXH    |--> */ RPLPOINT_TYPE_STD,
-/* RPLPOINT_TYPE_SBR    |--> */ RPLPOINT_TYPE_STD,
-/* RPLPOINT_TYPE_CALL   |--> */ RPLPOINT_TYPE_CALL,
-/* RPLPOINT_TYPE_INLINE |--> */ RPLPOINT_TYPE_CALL,
-/* RPLPOINT_TYPE_RETURN |--> */ RPLPOINT_TYPE_RETURN,
-/* RPLPOINT_TYPE_BODY   |--> */ RPLPOINT_TYPE_STD
-};
-
-
-static void replace_read_executionstate(rplpoint *rp,
-                                                                               executionstate_t *es,
-                                                                               sourcestate_t *ss,
-                                                                               bool topframe)
-{
-       methodinfo    *m;
-       codeinfo      *code;
-       int            count;
-       int            i;
-       rplalloc      *ra;
-       sourceframe_t *frame;
-       int            topslot;
-       stackslot_t   *sp;
-       stackslot_t   *basesp;
-
-       code = code_find_codeinfo_for_pc(rp->pc);
-       m = rp->method;
-       topslot = TOP_IS_NORMAL;
-
-       /* stack pointer */
-
-       sp = (stackslot_t *) es->sp;
-
-       /* in some cases the top stack slot is passed in REG_ITMP1 */
-
-       if (rp->type == BBTYPE_EXH) {
-               topslot = TOP_IS_IN_ITMP1;
-       }
-
-       /* calculate base stack pointer */
-
-       basesp = sp + code->stackframesize;
-
-       /* create the source frame */
-
-       frame = replace_new_sourceframe(ss);
-       frame->method = rp->method;
-       frame->id = rp->id;
-       assert(rp->type >= 0 && rp->type < sizeof(replace_normalize_type_map)/sizeof(s4));
-       frame->type = replace_normalize_type_map[rp->type];
-       frame->fromrp = rp;
-       frame->fromcode = code;
-
-       /* read local variables */
-
-       count = m->maxlocals;
-       frame->javalocalcount = count;
-       frame->javalocals = DMNEW(replace_val_t, count);
-       frame->javalocaltype = DMNEW(u1, count);
-
-       /* mark values as undefined */
-       for (i=0; i<count; ++i) {
-#if !defined(NDEBUG)
-               frame->javalocals[i].l = (u8) 0x00dead0000dead00ULL;
-#endif
-               frame->javalocaltype[i] = TYPE_VOID;
-       }
-
-       /* some entries in the intregs array are not meaningful */
-       /*es->intregs[REG_ITMP3] = (u8) 0x11dead1111dead11ULL;*/
-#if !defined(NDEBUG)
-       es->intregs[REG_SP   ] = (ptrint) 0x11dead1111dead11ULL;
-#ifdef REG_PV
-       es->intregs[REG_PV   ] = (ptrint) 0x11dead1111dead11ULL;
-#endif
-#endif /* !defined(NDEBUG) */
-
-       /* read javalocals */
-
-       count = rp->regalloccount;
-       ra = rp->regalloc;
-
-       while (count && (i = ra->index) >= 0) {
-               assert(i < m->maxlocals);
-               frame->javalocaltype[i] = ra->type;
-               if (ra->type == TYPE_RET)
-                       frame->javalocals[i].i = ra->regoff;
-               else
-                       replace_read_value(es, ra, frame->javalocals + i);
-               ra++;
-               count--;
-       }
-
-       /* read instance, if this is the first rplpoint */
-
-#if defined(REPLACE_PATCH_DYNAMIC_CALL)
-       if (topframe && !(rp->method->flags & ACC_STATIC) && rp == code->rplpoints) {
-#if 1
-               /* we are at the start of the method body, so if local 0 is set, */
-               /* it is the instance.                                           */
-               if (frame->javalocaltype[0] == TYPE_ADR)
-                       frame->instance = frame->javalocals[0];
-#else
-               rplalloc instra;
-               methoddesc *md;
-
-               md = rp->method->parseddesc;
-               assert(md->params);
-               assert(md->paramcount >= 1);
-               instra.type = TYPE_ADR;
-               instra.regoff = md->params[0].regoff;
-               if (md->params[0].inmemory) {
-                       instra.flags = INMEMORY;
-                       instra.regoff += (1 + code->stackframesize) * SIZE_OF_STACKSLOT;
-               }
-               else {
-                       instra.flags = 0;
-               }
-               replace_read_value(es, &instra, &(frame->instance));
-#endif
-       }
-#if defined(__I386__)
-       else if (!(rp->method->flags & ACC_STATIC)) {
-               /* On i386 we always pass the first argument on stack. */
-               frame->instance.a = *(java_object_t **)(basesp + 1);
-       } 
-#endif
-#endif /* defined(REPLACE_PATCH_DYNAMIC_CALL) */
-
-       /* read stack slots */
-
-       frame->javastackdepth = count;
-       frame->javastack = DMNEW(replace_val_t, count);
-       frame->javastacktype = DMNEW(u1, count);
-
-#if !defined(NDEBUG)
-       /* mark values as undefined */
-       for (i=0; i<count; ++i) {
-               frame->javastack[i].l = (u8) 0x00dead0000dead00ULL;
-               frame->javastacktype[i] = TYPE_VOID;
-       }
-#endif /* !defined(NDEBUG) */
-
-       i = 0;
-
-       /* the first stack slot is special in SBR and EXH blocks */
-
-       if (topslot == TOP_IS_ON_STACK) {
-               assert(count);
-
-               assert(ra->index == RPLALLOC_STACK);
-               assert(ra->type == TYPE_ADR);
-               frame->javastack[i].p = sp[-1];
-               frame->javastacktype[i] = TYPE_ADR; /* XXX RET */
-               count--;
-               i++;
-               ra++;
-       }
-       else if (topslot == TOP_IS_IN_ITMP1) {
-               assert(count);
-
-               assert(ra->index == RPLALLOC_STACK);
-               assert(ra->type == TYPE_ADR);
-               frame->javastack[i].p = es->intregs[REG_ITMP1];
-               frame->javastacktype[i] = TYPE_ADR; /* XXX RET */
-               count--;
-               i++;
-               ra++;
-       }
-       else if (topslot == TOP_IS_VOID) {
-               assert(count);
-
-               assert(ra->index == RPLALLOC_STACK);
-               frame->javastack[i].l = 0;
-               frame->javastacktype[i] = TYPE_VOID;
-               count--;
-               i++;
-               ra++;
-       }
-
-       /* read remaining stack slots */
-
-       for (; count--; ra++) {
-               if (ra->index == RPLALLOC_SYNC) {
-                       assert(rp->type == RPLPOINT_TYPE_INLINE);
-
-                       /* only read synchronization slots when traversing an inline point */
-
-                       if (!topframe) {
-                               sourceframe_t *calleeframe = frame->down;
-                               assert(calleeframe);
-                               assert(calleeframe->syncslotcount == 0);
-                               assert(calleeframe->syncslots == NULL);
-
-                               calleeframe->syncslotcount = 1;
-                               calleeframe->syncslots = DMNEW(replace_val_t, 1);
-                               replace_read_value(es,ra,calleeframe->syncslots);
-                       }
-
-                       frame->javastackdepth--;
-                       continue;
-               }
-
-               assert(ra->index == RPLALLOC_STACK || ra->index == RPLALLOC_PARAM);
-
-               /* do not read parameters of calls down the call chain */
-
-               if (!topframe && ra->index == RPLALLOC_PARAM) {
-                       frame->javastackdepth--;
-               }
-               else {
-                       if (ra->type == TYPE_RET)
-                               frame->javastack[i].i = ra->regoff;
-                       else
-                               replace_read_value(es,ra,frame->javastack + i);
-                       frame->javastacktype[i] = ra->type;
-                       i++;
-               }
-       }
-}
-
-
-/* replace_write_executionstate ************************************************
-
-   Pop a source frame from the front of the frame list of the given source state
-   and write its values into the execution state.
-
-   IN:
-       rp...............replacement point for which execution state should be
-                           created
-          es...............the execution state to modify
-          ss...............the given source state
-          topframe.........true, if this is the last (top-most) source frame to be
-                           translated
-
-   OUT:
-       *es..............the execution state derived from the source state
-  
-*******************************************************************************/
-
-static void replace_write_executionstate(rplpoint *rp,
-                                                                                executionstate_t *es,
-                                                                                sourcestate_t *ss,
-                                                                                bool topframe)
-{
-       methodinfo     *m;
-       codeinfo       *code;
-       int             count;
-       int             i;
-       rplalloc       *ra;
-       sourceframe_t  *frame;
-       int             topslot;
-       stackslot_t    *sp;
-       stackslot_t    *basesp;
-
-       code = code_find_codeinfo_for_pc(rp->pc);
-       m = rp->method;
-       topslot = TOP_IS_NORMAL;
-
-       /* pop a source frame */
-
-       frame = ss->frames;
-       assert(frame);
-       ss->frames = frame->down;
-
-       /* calculate stack pointer */
-
-       sp = (stackslot_t *) es->sp;
-
-       basesp = sp + code->stackframesize;
-
-       /* in some cases the top stack slot is passed in REG_ITMP1 */
-
-       if (rp->type == BBTYPE_EXH) {
-               topslot = TOP_IS_IN_ITMP1;
-       }
-
-       /* write javalocals */
-
-       ra = rp->regalloc;
-       count = rp->regalloccount;
-
-       while (count && (i = ra->index) >= 0) {
-               assert(i < m->maxlocals);
-               assert(i < frame->javalocalcount);
-               assert(ra->type == frame->javalocaltype[i]);
-               if (ra->type == TYPE_RET) {
-                       /* XXX assert that it matches this rplpoint */
-               }
-               else
-                       replace_write_value(es, ra, frame->javalocals + i);
-               count--;
-               ra++;
-       }
-
-       /* write stack slots */
-
-       i = 0;
-
-       /* the first stack slot is special in SBR and EXH blocks */
-
-       if (topslot == TOP_IS_ON_STACK) {
-               assert(count);
-
-               assert(ra->index == RPLALLOC_STACK);
-               assert(i < frame->javastackdepth);
-               assert(frame->javastacktype[i] == TYPE_ADR);
-               sp[-1] = frame->javastack[i].p;
-               count--;
-               i++;
-               ra++;
-       }
-       else if (topslot == TOP_IS_IN_ITMP1) {
-               assert(count);
-
-               assert(ra->index == RPLALLOC_STACK);
-               assert(i < frame->javastackdepth);
-               assert(frame->javastacktype[i] == TYPE_ADR);
-               es->intregs[REG_ITMP1] = frame->javastack[i].p;
-               count--;
-               i++;
-               ra++;
-       }
-       else if (topslot == TOP_IS_VOID) {
-               assert(count);
-
-               assert(ra->index == RPLALLOC_STACK);
-               assert(i < frame->javastackdepth);
-               assert(frame->javastacktype[i] == TYPE_VOID);
-               count--;
-               i++;
-               ra++;
-       }
-
-       /* write remaining stack slots */
-
-       for (; count--; ra++) {
-               if (ra->index == RPLALLOC_SYNC) {
-                       assert(rp->type == RPLPOINT_TYPE_INLINE);
-
-                       /* only write synchronization slots when traversing an inline point */
-
-                       if (!topframe) {
-                               assert(frame->down);
-                               assert(frame->down->syncslotcount == 1); /* XXX need to understand more cases */
-                               assert(frame->down->syncslots != NULL);
-
-                               replace_write_value(es,ra,frame->down->syncslots);
-                       }
-                       continue;
-               }
-
-               assert(ra->index == RPLALLOC_STACK || ra->index == RPLALLOC_PARAM);
-
-               /* do not write parameters of calls down the call chain */
-
-               if (!topframe && ra->index == RPLALLOC_PARAM) {
-                       /* skip it */
-                       /*
-                       ra->index = RPLALLOC_PARAM;
-                       replace_val_t v;
-                       v.l = 0;
-                       replace_write_value(es,ra,&v);
-                       */
-               }
-               else {
-                       assert(i < frame->javastackdepth);
-                       assert(ra->type == frame->javastacktype[i]);
-                       if (ra->type == TYPE_RET) {
-                               /* XXX assert that it matches this rplpoint */
-                       }
-                       else {
-                               replace_write_value(es,ra,frame->javastack + i);
-                       }
-                       i++;
-               }
-       }
-
-       /* set new pc */
-
-       es->pc = rp->pc;
-}
-
-
-/* md_pop_stackframe ***********************************************************
-
-   Restore callee-saved registers (including the RA register),
-   set the stack pointer to the next stackframe,
-   set the PC to the return address of the popped frame.
-
-   *** This function imitates the effects of the method epilog ***
-   *** and returning from the method call.                     ***
-
-   IN:
-       es...............execution state
-
-   OUT:
-       *es..............the execution state after popping the stack frame
-                        NOTE: es->code and es->pv are NOT updated.
-
-*******************************************************************************/
-
-void md_pop_stackframe(executionstate_t *es)
-{
-       u1 *ra;
-       s4 ra_align_off;
-       s4 reg;
-       s4 i;
-       stackslot_t *basesp;
-       stackslot_t *sp;
-
-       assert(es->code);
-
-       /* alignment offset of RA */
-
-       ra_align_off = 0;
-#if defined(REPLACE_RA_BETWEEN_FRAMES)
-    if (es->code->stackframesize)
-               ra_align_off = SIZE_OF_STACKSLOT - SIZEOF_VOID_P;
-#endif
-
-       /* read the return address */
-
-#if defined(REPLACE_LEAFMETHODS_RA_REGISTER)
-       if (code_is_leafmethod(es->code))
-               ra = es->ra;
-       else
-#endif
-               ra = md_stacktrace_get_returnaddress(es->sp,
-                          SIZE_OF_STACKSLOT * es->code->stackframesize + ra_align_off);
-
-       /* calculate the base of the stack frame */
-
-       sp = (stackslot_t *) es->sp;
-       basesp = sp + es->code->stackframesize;
-
-       /* restore return address, if part of frame */
-
-#if defined(REPLACE_RA_TOP_OF_FRAME)
-#if defined(REPLACE_LEAFMETHODS_RA_REGISTER)
-       if (!code_is_leafmethod(es->code))
-#endif
-               es->ra = (u1*) (ptrint) *--basesp;
-#endif /* REPLACE_RA_TOP_OF_FRAME */
-
-#if defined(REPLACE_RA_LINKAGE_AREA)
-#if defined(REPLACE_LEAFMETHODS_RA_REGISTER)
-       if (!code_is_leafmethod(es->code))
-#endif
-               es->ra = (u1*) (ptrint) basesp[LA_LR_OFFSET / sizeof(stackslot_t)];
-#endif /* REPLACE_RA_LINKAGE_AREA */
-
-       /* restore saved int registers */
-
-       reg = INT_REG_CNT;
-       for (i=0; i<es->code->savedintcount; ++i) {
-               while (nregdescint[--reg] != REG_SAV)
-                       ;
-               es->intregs[reg] = *--basesp;
-       }
-
-       /* restore saved flt registers */
-
-       /* XXX align? */
-       reg = FLT_REG_CNT;
-       for (i=0; i<es->code->savedfltcount; ++i) {
-               while (nregdescfloat[--reg] != REG_SAV)
-                       ;
-               basesp -= STACK_SLOTS_PER_FLOAT;
-               es->fltregs[reg] = *(double*)basesp;
-       }
-
-#if defined(HAS_ADDRESS_REGISTER_FILE)
-       /* restore saved adr registers */
-
-       reg = ADR_REG_CNT;
-       for (i=0; i<es->code->savedadrcount; ++i) {
-               while (nregdescadr[--reg] != REG_SAV)
-                       ;
-               es->adrregs[reg] = *--basesp;
-       }
-#endif
-
-       /* adjust the stackpointer */
-
-       es->sp += SIZE_OF_STACKSLOT * es->code->stackframesize;
-
-#if defined(REPLACE_RA_BETWEEN_FRAMES)
-       es->sp += ra_align_off + SIZEOF_VOID_P; /* skip return address */
-#endif
-
-       /* set the program counter to the return address */
-
-       es->pc = ra;
-
-       /* in debugging mode clobber non-saved registers */
-
-#if !defined(NDEBUG)
-       /* for debugging */
-       for (i=0; i<INT_REG_CNT; ++i)
-               if (nregdescint[i] != REG_SAV)
-                       es->intregs[i] = (ptrint) 0x33dead3333dead33ULL;
-       for (i=0; i<FLT_REG_CNT; ++i)
-               if (nregdescfloat[i] != REG_SAV)
-                       *(u8*)&(es->fltregs[i]) = 0x33dead3333dead33ULL;
-# if defined(HAS_ADDRESS_REGISTER_FILE)
-       for (i=0; i<ADR_REG_CNT; ++i)
-               if (nregdescadr[i] != REG_SAV)
-                       es->adrregs[i] = (ptrint) 0x33dead3333dead33ULL;
-# endif
-#endif /* !defined(NDEBUG) */
-}
-
-
-/* md_push_stackframe **********************************************************
-
-   Save the given return address, build the new stackframe,
-   and store callee-saved registers.
-
-   *** This function imitates the effects of a call and the ***
-   *** method prolog of the callee.                         ***
-
-   IN:
-       es...............execution state
-       calleecode.......the code we are "calling"
-       ra...............the return address to save
-
-   OUT:
-       *es..............the execution state after pushing the stack frame
-                        NOTE: es->pc, es->code, and es->pv are NOT updated.
-
-*******************************************************************************/
-
-void md_push_stackframe(executionstate_t *es, codeinfo *calleecode, u1 *ra)
-{
-       s4           reg;
-       s4           i;
-       stackslot_t *basesp;
-       stackslot_t *sp;
-
-       assert(es);
-       assert(calleecode);
-
-       /* write the return address */
-
-#if defined(REPLACE_RA_BETWEEN_FRAMES)
-       es->sp -= SIZEOF_VOID_P;
-       *((void **)es->sp) = (void *) ra;
-       if (calleecode->stackframesize)
-               es->sp -= (SIZE_OF_STACKSLOT - SIZEOF_VOID_P);
-#endif /* REPLACE_RA_BETWEEN_FRAMES */
-
-       es->ra = (u1*) (ptrint) ra;
-
-       /* build the stackframe */
-
-       DOLOG( printf("building stackframe of %d words at %p\n",
-                                 calleecode->stackframesize, (void*)es->sp); );
-
-       sp = (stackslot_t *) es->sp;
-       basesp = sp;
-
-       sp -= calleecode->stackframesize;
-       es->sp = (u1*) sp;
-
-       /* in debug mode, invalidate stack frame first */
-
-       /* XXX may not invalidate linkage area used by native code! */
-
-#if !defined(NDEBUG) && 0
-       for (i=0; i< (basesp - sp) && i < 1; ++i) {
-               sp[i] = 0xdeaddeadU;
-       }
-#endif
-
-#if defined(__I386__)
-       /* Stackslot 0 may contain the object instance for vftbl patching.
-          Destroy it, so there's no undefined value used. */
-       if ((basesp - sp) > 0) {
-               sp[0] = 0;
-       }
-#endif
-
-       /* save the return address register */
-
-#if defined(REPLACE_RA_TOP_OF_FRAME)
-#if defined(REPLACE_LEAFMETHODS_RA_REGISTER)
-       if (!code_is_leafmethod(calleecode))
-#endif
-               *--basesp = (ptrint) ra;
-#endif /* REPLACE_RA_TOP_OF_FRAME */
-
-#if defined(REPLACE_RA_LINKAGE_AREA)
-#if defined(REPLACE_LEAFMETHODS_RA_REGISTER)
-       if (!code_is_leafmethod(calleecode))
-#endif
-               basesp[LA_LR_OFFSET / sizeof(stackslot_t)] = (ptrint) ra;
-#endif /* REPLACE_RA_LINKAGE_AREA */
-
-       /* save int registers */
-
-       reg = INT_REG_CNT;
-       for (i=0; i<calleecode->savedintcount; ++i) {
-               while (nregdescint[--reg] != REG_SAV)
-                       ;
-               *--basesp = es->intregs[reg];
-
-               /* XXX may not clobber saved regs used by native code! */
-#if !defined(NDEBUG) && 0
-               es->intregs[reg] = (ptrint) 0x44dead4444dead44ULL;
-#endif
-       }
-
-       /* save flt registers */
-
-       /* XXX align? */
-       reg = FLT_REG_CNT;
-       for (i=0; i<calleecode->savedfltcount; ++i) {
-               while (nregdescfloat[--reg] != REG_SAV)
-                       ;
-               basesp -= STACK_SLOTS_PER_FLOAT;
-               *(double*)basesp = es->fltregs[reg];
-
-               /* XXX may not clobber saved regs used by native code! */
-#if !defined(NDEBUG) && 0
-               *(u8*)&(es->fltregs[reg]) = 0x44dead4444dead44ULL;
-#endif
-       }
-
-#if defined(HAS_ADDRESS_REGISTER_FILE)
-       /* save adr registers */
-
-       reg = ADR_REG_CNT;
-       for (i=0; i<calleecode->savedadrcount; ++i) {
-               while (nregdescadr[--reg] != REG_SAV)
-                       ;
-               *--basesp = es->adrregs[reg];
-
-               /* XXX may not clobber saved regs used by native code! */
-#if !defined(NDEBUG) && 0
-               es->adrregs[reg] = (ptrint) 0x44dead4444dead44ULL;
-#endif
-       }
-#endif
-}
-
-
-/* replace_pop_activation_record ***********************************************
-
-   Peel a stack frame from the execution state.
-
-   *** This function imitates the effects of the method epilog ***
-   *** and returning from the method call.                     ***
-
-   IN:
-       es...............execution state
-       frame............source frame, receives synchronization slots
-
-   OUT:
-       *es..............the execution state after popping the stack frame
-
-   RETURN VALUE:
-       the return address of the poped activation record
-
-*******************************************************************************/
-
-u1* replace_pop_activation_record(executionstate_t *es,
-                                                                 sourceframe_t *frame)
-{
-       u1 *ra;
-       u1 *pv;
-       s4 i;
-       s4 count;
-       codeinfo *code;
-       stackslot_t *sp;
-
-       assert(es->code);
-       assert(frame);
-
-       /* calculate the base of the stack frame */
-
-       sp = (stackslot_t *) es->sp;
-       assert(frame->syncslotcount == 0);
-       assert(frame->syncslots == NULL);
-       count = code_get_sync_slot_count(es->code);
-       frame->syncslotcount = count;
-       frame->syncslots = DMNEW(replace_val_t, count);
-       for (i=0; i<count; ++i) {
-               frame->syncslots[i].p = sp[es->code->memuse + i]; /* XXX md_ function */
-       }
-
-       /* pop the stackframe */
-
-       md_pop_stackframe(es);
-
-       ra = es->pc;
-
-       DOLOG( printf("RA = %p\n", (void*)ra); );
-
-       /* Subtract one from the PC so we do not hit the replacement point */
-       /* of the instruction following the call, if there is one.         */
-
-       es->pc--;
-
-       /* find the new codeinfo */
-
-       pv = md_codegen_get_pv_from_pc(ra);
-       DOLOG( printf("PV = %p\n", (void*) pv); );
-
-       code = code_get_codeinfo_for_pv(pv);
-       DOLOG( printf("CODE = %p\n", (void*) code); );
-
-       /* return NULL if we reached native code */
-
-       es->pv = pv;
-       es->code = code;
-
-       return (code) ? ra : NULL;
-}
-
-
-/* replace_patch_method_pointer ************************************************
-
-   Patch a method pointer (may be in code, data segment, vftbl, or interface
-   table).
-
-   IN:
-          mpp..............address of the method pointer to patch
-          entrypoint.......the new entrypoint of the method
-          kind.............kind of call to patch, used only for debugging
-
-*******************************************************************************/
-
-static void replace_patch_method_pointer(methodptr *mpp,
-                                                                                methodptr entrypoint,
-                                                                                const char *kind)
-{
-#if !defined(NDEBUG)
-       codeinfo       *oldcode;
-       codeinfo       *newcode;
-#endif
-
-       DOLOG( printf("patch method pointer from: %p to %p\n",
-                                 (void*) *mpp, (void*)entrypoint); );
-
-#if !defined(NDEBUG)
-       oldcode = code_get_codeinfo_for_pv(*mpp);
-       newcode = code_get_codeinfo_for_pv(entrypoint);
-
-       DOLOG_SHORT( printf("\tpatch %s %p ", kind, (void*) oldcode);
-                                method_println(oldcode->m);
-                                printf("\t      with      %p ", (void*) newcode);
-                                method_println(newcode->m); );
-
-       assert(oldcode->m == newcode->m);
-#endif
-
-       /* write the new entrypoint */
-
-       *mpp = (methodptr) entrypoint;
-}
-
-
-/* replace_patch_class *********************************************************
-
-   Patch a method in the given class.
-
-   IN:
-          vftbl............vftbl of the class
-          m................the method to patch
-          oldentrypoint....the old entrypoint to replace
-          entrypoint.......the new entrypoint
-
-*******************************************************************************/
-
-void replace_patch_class(vftbl_t *vftbl,
-                                                methodinfo *m,
-                                                u1 *oldentrypoint,
-                                                u1 *entrypoint)
-{
-       s4                 i;
-       methodptr         *mpp;
-       methodptr         *mppend;
-
-       /* patch the vftbl of the class */
-
-       replace_patch_method_pointer(vftbl->table + m->vftblindex,
-                                                                entrypoint,
-                                                                "virtual  ");
-
-       /* patch the interface tables */
-
-       assert(oldentrypoint);
-
-       for (i=0; i < vftbl->interfacetablelength; ++i) {
-               mpp = vftbl->interfacetable[-i];
-               mppend = mpp + vftbl->interfacevftbllength[i];
-               for (; mpp != mppend; ++mpp)
-                       if (*mpp == oldentrypoint) {
-                               replace_patch_method_pointer(mpp, entrypoint, "interface");
-                       }
-       }
-}
-
-
-/* replace_patch_class_hierarchy ***********************************************
-
-   Patch a method in all loaded classes.
-
-   IN:
-          m................the method to patch
-          oldentrypoint....the old entrypoint to replace
-          entrypoint.......the new entrypoint
-
-*******************************************************************************/
-
-struct replace_patch_data_t {
-       methodinfo *m;
-       u1         *oldentrypoint;
-       u1         *entrypoint;
-};
-
-void replace_patch_callback(classinfo *c, struct replace_patch_data_t *pd)
-{
-       vftbl_t *vftbl = c->vftbl;
-
-       if (vftbl != NULL
-               && vftbl->vftbllength > pd->m->vftblindex
-               && vftbl->table[pd->m->vftblindex] != &asm_abstractmethoderror
-               && code_get_methodinfo_for_pv(vftbl->table[pd->m->vftblindex]) == pd->m)
-       {
-               replace_patch_class(c->vftbl, pd->m, pd->oldentrypoint, pd->entrypoint);
-       }
-}
-
-void replace_patch_class_hierarchy(methodinfo *m,
-                                                                  u1 *oldentrypoint,
-                                                                  u1 *entrypoint)
-{
-       struct replace_patch_data_t pd;
-
-       pd.m = m;
-       pd.oldentrypoint = oldentrypoint;
-       pd.entrypoint = entrypoint;
-
-       DOLOG_SHORT( printf("patching class hierarchy: ");
-                            method_println(m); );
-
-       classcache_foreach_loaded_class(
-                       (classcache_foreach_functionptr_t) &replace_patch_callback,
-                       (void*) &pd);
-}
-
-
-/* replace_patch_future_calls **************************************************
-
-   Analyse a call site and depending on the kind of call patch the call, the
-   virtual function table, or the interface table.
-
-   IN:
-          ra...............return address pointing after the call site
-          callerframe......source frame of the caller
-          calleeframe......source frame of the callee, must have been mapped
-
-*******************************************************************************/
-
-void replace_patch_future_calls(u1 *ra,
-                                                               sourceframe_t *callerframe,
-                                                               sourceframe_t *calleeframe)
-{
-       u1            *patchpos;
-       methodptr      entrypoint;
-       methodptr      oldentrypoint;
-       bool           atentry;
-       void          *pv;
-       codeinfo      *calleecode;
-       methodinfo    *calleem;
-       java_object_t *obj;
-       vftbl_t       *vftbl;
-
-       assert(ra);
-       assert(callerframe->down == calleeframe);
-
-       /* get the new codeinfo and the method that shall be entered */
-
-       calleecode = calleeframe->tocode;
-       assert(calleecode);
-
-       calleem = calleeframe->method;
-       assert(calleem == calleecode->m);
-
-       entrypoint = (methodptr) calleecode->entrypoint;
-
-       /* check if we are at an method entry rplpoint at the innermost frame */
-
-       atentry = (calleeframe->down == NULL)
-                       && !(calleem->flags & ACC_STATIC)
-                       && (calleeframe->fromrp->id == 0); /* XXX */
-
-       /* get the position to patch, in case it was a statically bound call   */
-
-       pv = callerframe->fromcode->entrypoint;
-       patchpos = md_jit_method_patch_address(pv, ra, NULL);
-
-       if (patchpos == NULL) {
-               /* the call was dispatched dynamically */
-
-               /* we can only patch such calls if we are at the entry point */
-
-#if !defined(__I386__)
-               /* On i386 we always know the instance argument. */
-               if (!atentry)
-                       return;
-#endif
-
-               assert((calleem->flags & ACC_STATIC) == 0);
-
-               oldentrypoint = calleeframe->fromcode->entrypoint;
-
-               /* we need to know the instance */
-
-               if (!calleeframe->instance.a) {
-                       DOLOG_SHORT( printf("WARNING: object instance unknown!\n"); );
-                       replace_patch_class_hierarchy(calleem, oldentrypoint, entrypoint);
-                       return;
-               }
-
-               /* get the vftbl */
-
-               obj = calleeframe->instance.a;
-               vftbl = obj->vftbl;
-
-               assert(vftbl->clazz->vftbl == vftbl);
-
-               DOLOG_SHORT( printf("\tclass: "); class_println(vftbl->clazz); );
-
-               replace_patch_class(vftbl, calleem, oldentrypoint, entrypoint);
-       }
-       else {
-               /* the call was statically bound */
-
-#if defined(__I386__)
-               /* It happens that there is a patcher trap. (pm) */
-               if (*(u2 *)(patchpos - 1) == 0x0b0f) {
-               } else
-#endif
-               replace_patch_method_pointer((methodptr *) patchpos, entrypoint, "static   ");
-       }
-}
-
-
-/* replace_push_activation_record **********************************************
-
-   Push a stack frame onto the execution state.
-   
-   *** This function imitates the effects of a call and the ***
-   *** method prolog of the callee.                         ***
-
-   IN:
-          es...............execution state
-          rpcall...........the replacement point at the call site
-          callerframe......source frame of the caller, or NULL for creating the
-                           first frame
-          calleeframe......source frame of the callee, must have been mapped
-
-   OUT:
-       *es..............the execution state after pushing the stack frame
-  
-*******************************************************************************/
-
-void replace_push_activation_record(executionstate_t *es,
-                                                                       rplpoint *rpcall,
-                                                                       sourceframe_t *callerframe,
-                                                                       sourceframe_t *calleeframe)
-{
-       s4           i;
-       s4           count;
-       stackslot_t *sp;
-       u1          *ra;
-       codeinfo    *calleecode;
-
-       assert(es);
-       assert(!rpcall || callerframe);
-    assert(!rpcall || rpcall->type == RPLPOINT_TYPE_CALL);
-       assert(!rpcall || rpcall == callerframe->torp);
-       assert(calleeframe);
-       assert(!callerframe || calleeframe == callerframe->down);
-
-       /* the compilation unit we are entering */
-
-       calleecode = calleeframe->tocode;
-       assert(calleecode);
-
-       /* calculate the return address */
-
-       if (rpcall)
-               ra = rpcall->pc + rpcall->callsize;
-       else
-               ra = es->pc + 1 /* XXX this is ugly */;
-
-       /* push the stackframe */
-
-       md_push_stackframe(es, calleecode, ra);
-
-       /* we move into a new code unit, set code, PC, PV */
-
-       es->code = calleecode;
-       es->pc = calleecode->entrypoint; /* XXX not needed? */
-       es->pv = calleecode->entrypoint;
-
-       /* write slots used for synchronization */
-
-       sp = (stackslot_t *) es->sp;
-       count = code_get_sync_slot_count(calleecode);
-       assert(count == calleeframe->syncslotcount);
-       for (i=0; i<count; ++i) {
-               sp[calleecode->memuse + i] = calleeframe->syncslots[i].p;
-       }
-
-       /* redirect future invocations */
-
-       if (callerframe && rpcall) {
-#if defined(REPLACE_PATCH_ALL)
-               if (rpcall->type == callerframe->fromrp->type)
-#else
-               if (rpcall == callerframe->fromrp)
-#endif
-                       replace_patch_future_calls(ra, callerframe, calleeframe);
-       }
-}
-
-
-/* replace_find_replacement_point **********************************************
-
-   Find the replacement point in the given code corresponding to the
-   position given in the source frame.
-   
-   IN:
-          code.............the codeinfo in which to search the rplpoint
-          frame............the source frame defining the position to look for
-          parent...........parent replacement point to match
-
-   RETURN VALUE:
-       the replacement point
-  
-*******************************************************************************/
-
-rplpoint * replace_find_replacement_point(codeinfo *code,
-                                                                                 sourceframe_t *frame,
-                                                                                 rplpoint *parent)
-{
-       methodinfo *m;
-       rplpoint *rp;
-       s4        i;
-       s4        j;
-       s4        stacki;
-       rplalloc *ra;
-
-       assert(code);
-       assert(frame);
-
-       DOLOG( printf("searching replacement point for:\n");
-                  replace_source_frame_println(frame); );
-
-       m = frame->method;
-
-       DOLOG( printf("code = %p\n", (void*)code); );
-
-       rp = code->rplpoints;
-       i = code->rplpointcount;
-       while (i--) {
-               if (rp->id == frame->id && rp->method == frame->method
-                               && rp->parent == parent
-                               && replace_normalize_type_map[rp->type] == frame->type)
-               {
-                       /* check if returnAddresses match */
-                       /* XXX optimize: only do this if JSRs in method */
-                       DOLOG( printf("checking match for:");
-                                  replace_replacement_point_println(rp, 1); fflush(stdout); );
-                       ra = rp->regalloc;
-                       stacki = 0;
-                       for (j = rp->regalloccount; j--; ++ra) {
-                               if (ra->type == TYPE_RET) {
-                                       if (ra->index == RPLALLOC_STACK) {
-                                               assert(stacki < frame->javastackdepth);
-                                               if (frame->javastack[stacki].i != ra->regoff)
-                                                       goto no_match;
-                                               stacki++;
-                                       }
-                                       else {
-                                               assert(ra->index >= 0 && ra->index < frame->javalocalcount);
-                                               if (frame->javalocals[ra->index].i != ra->regoff)
-                                                       goto no_match;
-                                       }
-                               }
-                       }
-
-                       /* found */
-                       return rp;
-               }
-no_match:
-               rp++;
-       }
-
-#if !defined(NDEBUG)
-       printf("candidate replacement points were:\n");
-       rp = code->rplpoints;
-       i = code->rplpointcount;
-       for (; i--; ++rp) {
-               replace_replacement_point_println(rp, 1);
-       }
-#endif
-
-       vm_abort("no matching replacement point found");
-       return NULL; /* NOT REACHED */
-}
-
-
-/* replace_find_replacement_point_for_pc ***************************************
-
-   Find the nearest replacement point at or before the given PC. The
-   given PC has to be between (rp->pc) and (rp->pc+rp->callsize) for
-   the replacement point to be found.
-
-   IN:
-       code.............compilation unit the PC is in
-          pc...............the machine code PC
-
-   RETURN VALUE:
-       the replacement point found, or
-          NULL if no replacement point was found
-
-*******************************************************************************/
-
-rplpoint *replace_find_replacement_point_for_pc(codeinfo *code, u1 *pc, unsigned desired_flags)
-{
-       rplpoint *found;
-       rplpoint *rp;
-       s4        i;
-
-       DOLOG( printf("searching for rp at pc:%p in %p ", (void*)pc, (void*)code);
-                  method_println(code->m); );
-
-       found = NULL;
-
-       rp = code->rplpoints;
-       for (i=0; i<code->rplpointcount; ++i, ++rp) {
-               DOLOG( replace_replacement_point_println(rp, 2); );
-               if (rp->pc <= pc && rp->pc + rp->callsize >= pc) {
-                       if (desired_flags) {
-                               if (rp->flags & desired_flags) {
-                                       found = rp;
-                               }
-                       } else {
-                               found = rp;
-                       }
-               }
-       }
-
-       return found;
-}
-
-/* replace_pop_native_frame ****************************************************
-
-   Unroll a native frame in the execution state and create a source frame
-   for it.
-
-   IN:
-          es...............current execution state
-          ss...............the current source state
-          sfi..............stackframeinfo for the native frame
-
-   OUT:
-       es...............execution state after unrolling the native frame
-          ss...............gets the added native source frame
-
-*******************************************************************************/
-
-static void replace_pop_native_frame(executionstate_t *es,
-                                                                        sourcestate_t *ss,
-                                                                        stackframeinfo_t *sfi)
-{
-       sourceframe_t *frame;
-       codeinfo      *code;
-       s4             i,j;
-
-       assert(sfi);
-
-       frame = replace_new_sourceframe(ss);
-
-       frame->sfi = sfi;
-
-       /* remember pc and size of native frame */
-
-       frame->nativepc = es->pc;
-       frame->nativeframesize = (es->sp != 0) ? (((uintptr_t) sfi->sp) - ((uintptr_t) es->sp)) : 0;
-       assert(frame->nativeframesize >= 0);
-
-       /* remember values of saved registers */
-
-       j = 0;
-       for (i=0; i<INT_REG_CNT; ++i) {
-               if (nregdescint[i] == REG_SAV)
-                       frame->nativesavint[j++] = es->intregs[i];
-       }
-
-       j = 0;
-       for (i=0; i<FLT_REG_CNT; ++i) {
-               if (nregdescfloat[i] == REG_SAV)
-                       frame->nativesavflt[j++] = es->fltregs[i];
-       }
-
-#if defined(HAS_ADDRESS_REGISTER_FILE)
-       j = 0;
-       for (i=0; i<ADR_REG_CNT; ++i) {
-               if (nregdescadr[i] == REG_SAV)
-                       frame->nativesavadr[j++] = es->adrregs[i];
-       }
-#endif
-
-       /* restore saved registers */
-
-#if defined(ENABLE_GC_CACAO) && !defined(HAS_ADDRESS_REGISTER_FILE)
-       j = 0;
-       for (i=0; i<INT_REG_CNT; ++i) {
-               if (nregdescint[i] == REG_SAV)
-                       es->intregs[i] = sfi->intregs[j++];
-       }
-#else
-       /* XXX we don't have them, yet, in the sfi, so clear them */
-
-       for (i=0; i<INT_REG_CNT; ++i) {
-               if (nregdescint[i] == REG_SAV)
-                       es->intregs[i] = 0;
-       }
-#endif
-
-       /* XXX we don't have float registers in the sfi, so clear them */
-
-       for (i=0; i<FLT_REG_CNT; ++i) {
-               if (nregdescfloat[i] == REG_SAV)
-                       es->fltregs[i] = 0.0;
-       }
-
-#if defined(HAS_ADDRESS_REGISTER_FILE)
-# if defined(ENABLE_GC_CACAO)
-       j = 0;
-       for (i=0; i<ADR_REG_CNT; ++i) {
-               if (nregdescadr[i] == REG_SAV)
-                       es->adrregs[i] = sfi->adrregs[j++];
-       }
-# else
-       for (i=0; i<ADR_REG_CNT; ++i) {
-               if (nregdescadr[i] == REG_SAV)
-                       es->adrregs[i] = 0;
-       }
-# endif
-#endif
-
-       /* restore codeinfo of the native stub */
-
-       code = code_get_codeinfo_for_pv(sfi->pv);
-
-       /* restore sp, pv, pc and codeinfo of the parent method */
-
-       /* XXX michi: use this instead:
-       es->sp = sfi->sp + code->stackframesize; */
-       es->sp   = (void*) (((uintptr_t) sfi->sp) + (*(s4 *) (((uintptr_t) sfi->pv) + FrameSize)));
-#if defined(REPLACE_RA_BETWEEN_FRAMES)
-       es->sp  += SIZE_OF_STACKSLOT; /* skip return address */
-#endif
-       es->pv   = md_codegen_get_pv_from_pc(sfi->ra);
-       es->pc   = (void*) (((uintptr_t) ((sfi->xpc) ? sfi->xpc : sfi->ra)) - 1);
-       es->code = code_get_codeinfo_for_pv(es->pv);
-}
-
-
-/* replace_push_native_frame ***************************************************
-
-   Rebuild a native frame onto the execution state and remove its source frame.
-
-   Note: The native frame is "rebuild" by setting fields like PC and stack
-         pointer in the execution state accordingly. Values in the
-                stackframeinfo may be modified, but the actual stack frame of the
-                native code is not touched.
-
-   IN:
-          es...............current execution state
-          ss...............the current source state
-
-   OUT:
-       es...............execution state after re-rolling the native frame
-          ss...............the native source frame is removed
-
-*******************************************************************************/
-
-static void replace_push_native_frame(executionstate_t *es, sourcestate_t *ss)
-{
-       sourceframe_t *frame;
-       s4             i,j;
-
-       assert(es);
-       assert(ss);
-
-       DOLOG( printf("pushing native frame\n"); );
-
-       /* remove the frame from the source state */
-
-       frame = ss->frames;
-       assert(frame);
-       assert(REPLACE_IS_NATIVE_FRAME(frame));
-
-       ss->frames = frame->down;
-
-       /* skip sp for the native stub */
-
-       es->sp -= (*(s4 *) (((uintptr_t) frame->sfi->pv) + FrameSize));
-#if defined(REPLACE_RA_BETWEEN_FRAMES)
-       es->sp -= SIZE_OF_STACKSLOT; /* skip return address */
-#endif
-
-       /* assert that the native frame has not moved */
-
-       assert(es->sp == frame->sfi->sp);
-
-       /* update saved registers in the stackframeinfo */
-
-#if defined(ENABLE_GC_CACAO)
-       j = 0;
-# if !defined(HAS_ADDRESS_REGISTER_FILE)
-       for (i=0; i<INT_REG_CNT; ++i) {
-               if (nregdescint[i] == REG_SAV)
-                       frame->sfi->intregs[j++] = es->intregs[i];
-       }
-# else
-       for (i=0; i<ADR_REG_CNT; ++i) {
-               if (nregdescadr[i] == REG_SAV)
-                       frame->sfi->adrregs[j++] = es->adrregs[i];
-       }
-# endif
-
-       /* XXX leave float registers untouched here */
-#endif
-
-       /* restore saved registers */
-
-       j = 0;
-       for (i=0; i<INT_REG_CNT; ++i) {
-               if (nregdescint[i] == REG_SAV)
-                       es->intregs[i] = frame->nativesavint[j++];
-       }
-
-       j = 0;
-       for (i=0; i<FLT_REG_CNT; ++i) {
-               if (nregdescfloat[i] == REG_SAV)
-                       es->fltregs[i] = frame->nativesavflt[j++];
-       }
-
-#if defined(HAS_ADDRESS_REGISTER_FILE)
-       j = 0;
-       for (i=0; i<ADR_REG_CNT; ++i) {
-               if (nregdescadr[i] == REG_SAV)
-                       es->adrregs[i] = frame->nativesavadr[j++];
-       }
-#endif
-
-       /* skip the native frame on the machine stack */
-
-       es->sp -= frame->nativeframesize;
-
-       /* set the pc the next frame must return to */
-
-       es->pc = frame->nativepc;
-}
-
-
-/* replace_recover_source_state ************************************************
-
-   Recover the source state from the given replacement point and execution
-   state.
-
-   IN:
-       rp...............replacement point that has been reached, if any
-          sfi..............stackframeinfo, if called from native code
-          es...............execution state at the replacement point rp
-
-   RETURN VALUE:
-       the source state
-
-*******************************************************************************/
-
-sourcestate_t *replace_recover_source_state(rplpoint *rp,
-                                                                                       stackframeinfo_t *sfi,
-                                                                                   executionstate_t *es)
-{
-       sourcestate_t *ss;
-       u1            *ra;
-       bool           locked;
-#if defined(REPLACE_STATISTICS)
-       s4             depth;
-#endif
-
-       /* create the source frame structure in dump memory */
-
-       ss = DNEW(sourcestate_t);
-       ss->frames = NULL;
-
-       /* each iteration of the loop recovers one source frame */
-
-       depth = 0;
-       locked = false;
-
-       while (rp || sfi) {
-
-               DOLOG( executionstate_println(es); );
-
-               /* if we are not at a replacement point, it is a native frame */
-
-               if (rp == NULL) {
-                       DOLOG( printf("native frame: sfi: "); replace_stackframeinfo_println(sfi); );
-
-                       locked = true;
-                       replace_pop_native_frame(es, ss, sfi);
-                       sfi = sfi->prev;
-
-                       if (es->code == NULL)
-                               continue;
-
-                       goto after_machine_frame;
-               }
-
-               /* read the values for this source frame from the execution state */
-
-               DOLOG( printf("recovering source state for%s:\n",
-                                       (ss->frames == NULL) ? " TOPFRAME" : "");
-                          replace_replacement_point_println(rp, 1); );
-
-               replace_read_executionstate(rp, es, ss, ss->frames == NULL);
-
-#if defined(ENABLE_VMLOG)
-               vmlog_cacao_unrol_method(ss->frames->method);
-#endif
-
-#if defined(REPLACE_STATISTICS)
-               REPLACE_COUNT(stat_frames);
-               depth++;
-               replace_statistics_source_frame(ss->frames);
-#endif
-
-               /* in locked areas (below native frames), identity map the frame */
-
-               if (locked) {
-                       ss->frames->torp = ss->frames->fromrp;
-                       ss->frames->tocode = ss->frames->fromcode;
-               }
-
-               /* unroll to the next (outer) frame */
-
-               if (rp->parent) {
-                       /* this frame is in inlined code */
-
-                       DOLOG( printf("INLINED!\n"); );
-
-                       rp = rp->parent;
-
-                       assert(rp->type == RPLPOINT_TYPE_INLINE);
-                       REPLACE_COUNT(stat_unroll_inline);
-               }
-               else {
-                       /* this frame had been called at machine-level. pop it. */
-
-                       DOLOG( printf("UNWIND\n"); );
-
-                       ra = replace_pop_activation_record(es, ss->frames);
-                       if (ra == NULL) {
-                               DOLOG( printf("REACHED NATIVE CODE\n"); );
-
-                               rp = NULL;
-
-#if !defined(ENABLE_GC_CACAO)
-                               break; /* XXX remove to activate native frames */
-#endif
-                               continue;
-                       }
-
-                       /* find the replacement point at the call site */
-
-after_machine_frame:
-                       rp = replace_find_replacement_point_for_pc(es->code, es->pc, 0);
-
-                       if (rp == NULL)
-                               vm_abort("could not find replacement point while unrolling call");
-
-                       DOLOG( printf("found replacement point.\n");
-                                       replace_replacement_point_println(rp, 1); );
-
-                       assert(rp->type == RPLPOINT_TYPE_CALL);
-                       REPLACE_COUNT(stat_unroll_call);
-               }
-       } /* end loop over source frames */
-
-       REPLACE_COUNT_DIST(stat_dist_frames, depth);
-
-       return ss;
-}
-
-
-/* replace_map_source_state ****************************************************
-
-   Map each source frame in the given source state to a target replacement
-   point and compilation unit. If no valid code is available for a source
-   frame, it is (re)compiled.
-
-   IN:
-       ss...............the source state
-
-   OUT:
-       ss...............the source state, modified: The `torp` and `tocode`
-                           fields of each source frame are set.
-
-   RETURN VALUE:
-       true.............everything went ok
-          false............an exception has been thrown
-
-*******************************************************************************/
-
-static bool replace_map_source_state(sourcestate_t *ss)
-{
-       sourceframe_t *frame;
-       codeinfo      *code;
-       rplpoint      *rp;
-       rplpoint      *parent; /* parent of inlined rplpoint */
-#if defined(REPLACE_STATISTICS)
-       codeinfo      *oldcode;
-#endif
-
-       parent = NULL;
-       code = NULL;
-
-       /* iterate over the source frames from outermost to innermost */
-
-       for (frame = ss->frames; frame != NULL; frame = frame->down) {
-
-               /* XXX skip native frames */
-
-               if (REPLACE_IS_NATIVE_FRAME(frame)) {
-                       parent = NULL;
-                       continue;
-               }
-
-               /* map frames which are not already mapped */
-
-               if (frame->tocode) {
-                       code = frame->tocode;
-                       rp = frame->torp;
-                       assert(rp);
-               }
-               else {
-                       assert(frame->torp == NULL);
-
-                       if (parent == NULL) {
-                               /* find code for this frame */
-
-#if defined(REPLACE_STATISTICS)
-                               oldcode = frame->method->code;
-#endif
-                               /* request optimization of hot methods and their callers */
-
-                               if (frame->method->hitcountdown < 0
-                                       || (frame->down && frame->down->method->hitcountdown < 0))
-                                       jit_request_optimization(frame->method);
-
-                               code = jit_get_current_code(frame->method);
-
-                               if (code == NULL)
-                                       return false; /* exception */
-
-                               REPLACE_COUNT_IF(stat_recompile, code != oldcode);
-                       }
-
-                       assert(code);
-
-                       /* map this frame */
-
-                       rp = replace_find_replacement_point(code, frame, parent);
-
-                       frame->tocode = code;
-                       frame->torp = rp;
-               }
-
-               if (rp->type == RPLPOINT_TYPE_CALL) {
-                       parent = NULL;
-               }
-               else {
-                       /* inlining */
-                       parent = rp;
-               }
-       }
-
-       return true;
-}
-
-
-/* replace_map_source_state_identity *******************************************
-
-   Map each source frame in the given source state to the same replacement
-   point and compilation unit it was derived from. This is mainly used for
-   garbage collection.
-
-   IN:
-       ss...............the source state
-
-   OUT:
-       ss...............the source state, modified: The `torp` and `tocode`
-                           fields of each source frame are set.
-
-*******************************************************************************/
-
-#if defined(ENABLE_GC_CACAO)
-static void replace_map_source_state_identity(sourcestate_t *ss)
-{
-       sourceframe_t *frame;
-
-       /* iterate over the source frames from outermost to innermost */
-
-       for (frame = ss->frames; frame != NULL; frame = frame->down) {
-
-               /* skip native frames */
-
-               if (REPLACE_IS_NATIVE_FRAME(frame)) {
-                       continue;
-               }
-
-               /* map frames using the identity mapping */
-
-               if (frame->tocode) {
-                       assert(frame->tocode == frame->fromcode);
-                       assert(frame->torp   == frame->fromrp);
-               } else {
-                       assert(frame->tocode == NULL);
-                       assert(frame->torp   == NULL);
-                       frame->tocode = frame->fromcode;
-                       frame->torp   = frame->fromrp;
-               }
-       }
-}
-#endif
-
-
-/* replace_build_execution_state ***********************************************
-
-   Build an execution state for the given (mapped) source state.
-
-   !!! CAUTION: This function rewrites the machine stack !!!
-
-   THIS FUNCTION MUST BE CALLED USING A SAFE STACK AREA!
-
-   IN:
-       ss...............the source state. Must have been mapped by
-                                               replace_map_source_state before.
-          es...............the base execution state on which to build
-
-   OUT:
-       *es..............the new execution state
-
-*******************************************************************************/
-
-static void replace_build_execution_state(sourcestate_t *ss,
-                                                                                 executionstate_t *es)
-{
-       rplpoint      *rp;
-       sourceframe_t *prevframe;
-       rplpoint      *parent;
-
-       parent = NULL;
-       prevframe = NULL;
-       rp = NULL;
-
-       while (ss->frames) {
-
-               if (REPLACE_IS_NATIVE_FRAME(ss->frames)) {
-                       prevframe = ss->frames;
-                       replace_push_native_frame(es, ss);
-                       parent = NULL;
-                       rp = NULL;
-                       continue;
-               }
-
-               if (parent == NULL) {
-                       /* create a machine-level stack frame */
-
-                       DOLOG( printf("pushing activation record for:\n");
-                                  if (rp) replace_replacement_point_println(rp, 1);
-                                  else printf("\tfirst frame\n"); );
-
-                       replace_push_activation_record(es, rp, prevframe, ss->frames);
-
-                       DOLOG( executionstate_println(es); );
-               }
-
-               rp = ss->frames->torp;
-               assert(rp);
-
-               DOLOG( printf("creating execution state for%s:\n",
-                               (ss->frames->down == NULL) ? " TOPFRAME" : "");
-                          replace_replacement_point_println(ss->frames->fromrp, 1);
-                          replace_replacement_point_println(rp, 1); );
-
-               es->code = ss->frames->tocode;
-               prevframe = ss->frames;
-
-#if defined(ENABLE_VMLOG)
-               vmlog_cacao_rerol_method(ss->frames->method);
-#endif
-
-               replace_write_executionstate(rp, es, ss, ss->frames->down == NULL);
-
-               DOLOG( executionstate_println(es); );
-
-               if (rp->type == RPLPOINT_TYPE_CALL) {
-                       parent = NULL;
-               }
-               else {
-                       /* inlining */
-                       parent = rp;
-               }
-       }
-}
-
-
-/* replace_me ******************************************************************
-   This function is called by the signal handler when a thread reaches
-   a replacement point. `replace_me` must map the execution state to the
-   target replacement point and let execution continue there.
-
-   THIS FUNCTION MUST BE CALLED USING A SAFE STACK AREA!
-
-   IN:
-       rp...............replacement point that has been reached
-       es...............execution state read by signal handler
-  
-*******************************************************************************/
-
-static void replace_me(rplpoint *rp, executionstate_t *es)
-{
-       stackframeinfo_t    *sfi;
-       sourcestate_t       *ss;
-       sourceframe_t       *frame;
-       codeinfo            *origcode;
-       rplpoint            *origrp;
-#if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
-       threadobject        *thread;
-#endif
-       int32_t              dumpmarker;
-
-       origcode = es->code;
-       origrp   = rp;
-
-#if defined(ENABLE_TLH)
-       /*printf("Replacing in %s/%s\n", rp->method->clazz->name->text, rp->method->name->text);*/
-#endif
-
-       /*if (strcmp(rp->method->clazz->name->text, "antlr/AlternativeElement") == 0 && strcmp(rp->method->name->text, "getAutoGenType") ==0) opt_TraceReplacement = 2; else opt_TraceReplacement = 0;*/
-
-       DOLOG_SHORT( printf("REPLACING(%d %p): (id %d %p) ",
-                                stat_replacements, (void*)THREADOBJECT,
-                                rp->id, (void*)rp);
-                                method_println(es->code->m); );
-
-       DOLOG( replace_replacement_point_println(rp, 1); );
-
-       REPLACE_COUNT(stat_replacements);
-
-       /* mark start of dump memory area */
-
-       DMARKER;
-
-       /* Get the stackframeinfo for the current thread. */
-
-       sfi = threads_get_current_stackframeinfo();
-
-       /* recover source state */
-
-       ss = replace_recover_source_state(rp, sfi, es);
-
-#if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
-       /* if there is a collection pending, we assume the replacement point should
-          suspend this thread */
-
-       if (gc_pending) {
-
-               thread = THREADOBJECT;
-
-               DOLOG_SHORT( printf("REPLACEMENT: Suspending thread for GC now!\n"); );
-
-               /* map the sourcestate using the identity mapping */
-               replace_map_source_state_identity(ss);
-
-               /* since we enter the same method again, we turn off rps now */
-               /* XXX michi: can we really do this? what if the rp was active before
-                  we activated it for the gc? */
-               replace_deactivate_replacement_points(origcode);
-
-               /* remember executionstate and sourcestate for this thread */
-               GC_EXECUTIONSTATE = es;
-               GC_SOURCESTATE    = ss;
-
-               /* really suspend this thread now (PC = 0) */
-               threads_suspend_ack(NULL, NULL);
-
-               DOLOG_SHORT( printf("REPLACEMENT: Resuming thread after GC now!\n"); );
-
-       } else {
-#endif /*defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)*/
-
-       /* map the source state */
-
-       if (!replace_map_source_state(ss))
-               vm_abort("exception during method replacement");
-
-       DOLOG( replace_sourcestate_println(ss); );
-
-       DOLOG_SHORT( replace_sourcestate_println_short(ss); );
-
-#if !defined(NDEBUG)
-       /* avoid infinite loops by self-replacement, only if not in testing mode */
-
-       if (!opt_TestReplacement) {
-               frame = ss->frames;
-               while (frame->down)
-                       frame = frame->down;
-
-               if (frame->torp == origrp) {
-                       DOLOG_SHORT(
-                               printf("WARNING: identity replacement, turning off rps to avoid infinite loop\n");
-                       );
-                       replace_deactivate_replacement_points(origcode);
-               }
-       }
-#endif
-
-#if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
-       }
-#endif
-
-       /* build the new execution state */
-
-       replace_build_execution_state(ss, es);
-
-#if !defined(NDEBUG)
-       /* continue execution after patched machine code, if testing mode enabled */
-
-       if (opt_TestReplacement)
-               es->pc += REPLACEMENT_PATCH_SIZE;
-#endif
-
-       /* release dump area */
-
-       DRELEASE;
-}
-
-
-/* replace_me_wrapper **********************************************************
-
-   This function is called by the signal handler. It determines if there
-   is an active replacement point pending at the given PC and returns
-   accordingly.
-
-   THIS FUNCTION MUST BE CALLED USING A SAFE STACK AREA!
-
-   IN:
-       pc...............the program counter that triggered the replacement.
-       context..........the context (machine state) to which the
-                           replacement should be applied.
-
-   OUT:
-       context..........the context after replacement finished.
-
-   RETURN VALUE:
-       true.............replacement done, everything went ok
-       false............no replacement done, context unchanged
-
-*******************************************************************************/
-
-bool replace_me_wrapper(u1 *pc, void *context)
-{
-       codeinfo         *code;
-       rplpoint         *rp;
-       executionstate_t  es;
-#if defined(ENABLE_RT_TIMING)
-       struct timespec time_start, time_end;
-#endif
-
-       /* search the codeinfo for the given PC */
-
-       code = code_find_codeinfo_for_pc(pc);
-       assert(code);
-
-       /* search for a replacement point at the given PC */
-
-       rp = replace_find_replacement_point_for_pc(code, pc, (RPLPOINT_FLAG_ACTIVE | RPLPOINT_FLAG_COUNTDOWN));
-
-       /* check if the replacement point belongs to given PC and is active */
-
-       if ((rp != NULL) && (rp->pc == pc)
-           && (rp->flags & (RPLPOINT_FLAG_ACTIVE | RPLPOINT_FLAG_COUNTDOWN))) {
-
-               DOLOG( printf("valid replacement point\n"); );
-
-#if !defined(NDEBUG)
-               executionstate_sanity_check(context);
-#endif
-
-               /* set codeinfo pointer in execution state */
-
-               es.code = code;
-
-               /* read execution state from current context */
-
-               md_executionstate_read(&es, context);
-
-               DOLOG( printf("REPLACEMENT READ: ");
-                          executionstate_println(&es); );
-
-               /* do the actual replacement */
-
-#if defined(ENABLE_RT_TIMING)
-               RT_TIMING_GET_TIME(time_start);
-#endif
-
-               replace_me(rp, &es);
-
-#if defined(ENABLE_RT_TIMING)
-               RT_TIMING_GET_TIME(time_end);
-               RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_REPLACE);
-#endif
-
-               /* write execution state to current context */
-
-               md_executionstate_write(&es, context);
-
-               DOLOG( printf("REPLACEMENT WRITE: ");
-                          executionstate_println(&es); );
-
-               /* new code is entered after returning */
-
-               DOLOG( printf("JUMPING IN!\n"); fflush(stdout); );
-               return true;
-       }
-       else
-               return false;
-}
-
-
-/******************************************************************************/
-/* NOTE: Stuff specific to the exact GC is below.                             */
-/******************************************************************************/
-
-#if defined(ENABLE_GC_CACAO)
-void replace_gc_from_native(threadobject *thread, u1 *pc, u1 *sp)
-{
-       stackframeinfo_t *sfi;
-       executionstate_t *es;
-       sourcestate_t    *ss;
-
-       /* Get the stackframeinfo of this thread. */
-
-       assert(thread == THREADOBJECT);
-
-       sfi = threads_get_current_stackframeinfo();
-
-       /* create the execution state */
-       es = DNEW(executionstate_t);
-       es->pc = pc;
-       es->sp = sp;
-       es->pv = 0;      /* since we are in a native, PV is invalid! */
-       es->code = NULL; /* since we are in a native, we do not have a codeinfo */
-
-       /* we assume we are in a native (no replacement point)! */
-       ss = replace_recover_source_state(NULL, sfi, es);
-
-       /* map the sourcestate using the identity mapping */
-       replace_map_source_state_identity(ss);
-
-       /* remember executionstate and sourcestate for this thread */
-       GC_EXECUTIONSTATE = es;
-       GC_SOURCESTATE    = ss;
-}
-#endif
-
-#if defined(ENABLE_GC_CACAO)
-void replace_gc_into_native(threadobject *thread)
-{
-       executionstate_t *es;
-       sourcestate_t    *ss;
-
-       /* get the executionstate and sourcestate for the given thread */
-       es = GC_EXECUTIONSTATE;
-       ss = GC_SOURCESTATE;
-
-       /* rebuild the stack of the given thread */
-       replace_build_execution_state(ss, es);
-}
-#endif
-
-
-/******************************************************************************/
-/* NOTE: No important code below.                                             */
-/******************************************************************************/
-
-
-/* statistics *****************************************************************/
-
-#if defined(REPLACE_STATISTICS)
-static void print_freq(FILE *file,int *array,int limit)
-{
-       int i;
-       int sum = 0;
-       int cum = 0;
-       for (i=0; i<limit; ++i)
-               sum += array[i];
-       sum += array[limit];
-       for (i=0; i<limit; ++i) {
-               cum += array[i];
-               fprintf(file,"      %3d: %8d (cum %3d%%)\n",
-                               i, array[i], (sum) ? ((100*cum)/sum) : 0);
-       }
-       fprintf(file,"    >=%3d: %8d\n",limit,array[limit]);
-}
-#endif /* defined(REPLACE_STATISTICS) */
-
-
-#if defined(REPLACE_STATISTICS)
-
-#define REPLACE_PRINT_DIST(name, array)                              \
-    printf("    " name " distribution:\n");                          \
-    print_freq(stdout, (array), sizeof(array)/sizeof(int) - 1);
-
-void replace_print_statistics(void)
-{
-       printf("replacement statistics:\n");
-       printf("    # of replacements:   %d\n", stat_replacements);
-       printf("    # of frames:         %d\n", stat_frames);
-       printf("    # of recompilations: %d\n", stat_recompile);
-       printf("    patched static calls:%d\n", stat_staticpatch);
-       printf("    unrolled inlines:    %d\n", stat_unroll_inline);
-       printf("    unrolled calls:      %d\n", stat_unroll_call);
-       REPLACE_PRINT_DIST("frame depth", stat_dist_frames);
-       REPLACE_PRINT_DIST("locals per frame", stat_dist_locals);
-       REPLACE_PRINT_DIST("ADR locals per frame", stat_dist_locals_adr);
-       REPLACE_PRINT_DIST("primitive locals per frame", stat_dist_locals_prim);
-       REPLACE_PRINT_DIST("RET locals per frame", stat_dist_locals_ret);
-       REPLACE_PRINT_DIST("void locals per frame", stat_dist_locals_void);
-       REPLACE_PRINT_DIST("stack slots per frame", stat_dist_stack);
-       REPLACE_PRINT_DIST("ADR stack slots per frame", stat_dist_stack_adr);
-       REPLACE_PRINT_DIST("primitive stack slots per frame", stat_dist_stack_prim);
-       REPLACE_PRINT_DIST("RET stack slots per frame", stat_dist_stack_ret);
-       printf("\n");
-       printf("    # of methods:            %d\n", stat_methods);
-       printf("    # of replacement points: %d\n", stat_rploints);
-       printf("    # of regallocs:          %d\n", stat_regallocs);
-       printf("        per rplpoint:        %f\n", (double)stat_regallocs / stat_rploints);
-       printf("        per method:          %f\n", (double)stat_regallocs / stat_methods);
-       REPLACE_PRINT_DIST("replacement points per method", stat_dist_method_rplpoints);
-       printf("\n");
-
-}
-#endif /* defined(REPLACE_STATISTICS) */
-
-
-#if defined(REPLACE_STATISTICS)
-static void replace_statistics_source_frame(sourceframe_t *frame)
-{
-       int adr = 0;
-       int ret = 0;
-       int prim = 0;
-       int vd = 0;
-       int n = 0;
-       int i;
-
-       for (i=0; i<frame->javalocalcount; ++i) {
-               switch (frame->javalocaltype[i]) {
-                       case TYPE_ADR: adr++; break;
-                       case TYPE_RET: ret++; break;
-                       case TYPE_INT: case TYPE_LNG: case TYPE_FLT: case TYPE_DBL: prim++; break;
-                       case TYPE_VOID: vd++; break;
-                       default: assert(0);
-               }
-               n++;
-       }
-       REPLACE_COUNT_DIST(stat_dist_locals, n);
-       REPLACE_COUNT_DIST(stat_dist_locals_adr, adr);
-       REPLACE_COUNT_DIST(stat_dist_locals_void, vd);
-       REPLACE_COUNT_DIST(stat_dist_locals_ret, ret);
-       REPLACE_COUNT_DIST(stat_dist_locals_prim, prim);
-       adr = ret = prim = n = 0;
-       for (i=0; i<frame->javastackdepth; ++i) {
-               switch (frame->javastacktype[i]) {
-                       case TYPE_ADR: adr++; break;
-                       case TYPE_RET: ret++; break;
-                       case TYPE_INT: case TYPE_LNG: case TYPE_FLT: case TYPE_DBL: prim++; break;
-               }
-               n++;
-       }
-       REPLACE_COUNT_DIST(stat_dist_stack, n);
-       REPLACE_COUNT_DIST(stat_dist_stack_adr, adr);
-       REPLACE_COUNT_DIST(stat_dist_stack_ret, ret);
-       REPLACE_COUNT_DIST(stat_dist_stack_prim, prim);
-}
-#endif /* defined(REPLACE_STATISTICS) */
-
-
-/* debugging helpers **********************************************************/
-
-/* replace_replacement_point_println *******************************************
-   Print replacement point info.
-  
-   IN:
-       rp...............the replacement point to print
-  
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-
-#define TYPECHAR(t)  (((t) >= 0 && (t) <= TYPE_RET) ? show_jit_type_letters[t] : '?')
-
-static char *replace_type_str[] = {
-       "STD",
-       "EXH",
-       "SBR",
-       "CALL",
-       "INLINE",
-       "RETURN",
-       "BODY"
-};
-
-void replace_replacement_point_println(rplpoint *rp, int depth)
-{
-       int j;
-       int index;
-
-       if (!rp) {
-               printf("(rplpoint *)NULL\n");
-               return;
-       }
-
-       for (j=0; j<depth; ++j)
-               putchar('\t');
-
-       printf("rplpoint (id %d) %p pc:%p+%d type:%s",
-                       rp->id, (void*)rp,rp->pc,rp->callsize,
-                       replace_type_str[rp->type]);
-       if (rp->flags & RPLPOINT_FLAG_NOTRAP)
-               printf(" NOTRAP");
-       if (rp->flags & RPLPOINT_FLAG_COUNTDOWN)
-               printf(" COUNTDOWN");
-       if (rp->flags & RPLPOINT_FLAG_ACTIVE)
-               printf(" ACTIVE");
-       printf(" parent:%p\n", (void*)rp->parent);
-       for (j=0; j<depth; ++j)
-               putchar('\t');
-       printf("ra:%d = [",     rp->regalloccount);
-
-       for (j=0; j<rp->regalloccount; ++j) {
-               if (j)
-                       putchar(' ');
-               index = rp->regalloc[j].index;
-               switch (index) {
-                       case RPLALLOC_STACK: printf("S"); break;
-                       case RPLALLOC_PARAM: printf("P"); break;
-                       case RPLALLOC_SYNC : printf("Y"); break;
-                       default: printf("%d", index);
-               }
-               printf(":%1c:", TYPECHAR(rp->regalloc[j].type));
-               if (rp->regalloc[j].type == TYPE_RET) {
-                       printf("ret(L%03d)", rp->regalloc[j].regoff);
-               }
-               else {
-                       show_allocation(rp->regalloc[j].type, rp->regalloc[j].flags, rp->regalloc[j].regoff);
-               }
-       }
-
-       printf("]\n");
-       for (j=0; j<depth; ++j)
-               putchar('\t');
-       printf("method: ");
-       method_print(rp->method);
-
-       printf("\n");
-}
-#endif /* !defined(NDEBUG) */
-
-
-/* replace_show_replacement_points *********************************************
-   Print replacement point info.
-  
-   IN:
-       code.............codeinfo whose replacement points should be printed.
-  
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-void replace_show_replacement_points(codeinfo *code)
-{
-       int i;
-       int depth;
-       rplpoint *rp;
-       rplpoint *parent;
-
-       if (!code) {
-               printf("(codeinfo *)NULL\n");
-               return;
-       }
-
-       printf("\treplacement points: %d\n",code->rplpointcount);
-
-       printf("\ttotal allocations : %d\n",code->regalloccount);
-       printf("\tsaved int regs    : %d\n",code->savedintcount);
-       printf("\tsaved flt regs    : %d\n",code->savedfltcount);
-#if defined(HAS_ADDRESS_REGISTER_FILE)
-       printf("\tsaved adr regs    : %d\n",code->savedadrcount);
-#endif
-       printf("\tmemuse            : %d\n",code->memuse);
-
-       printf("\n");
-
-       for (i=0; i<code->rplpointcount; ++i) {
-               rp = code->rplpoints + i;
-
-               depth = 1;
-               parent = rp->parent;
-               while (parent) {
-                       depth++;
-                       parent = parent->parent;
-               }
-               replace_replacement_point_println(rp, depth);
-       }
-}
-#endif
-
-
-#if !defined(NDEBUG)
-static void java_value_print(s4 type, replace_val_t value)
-{
-       java_object_t *obj;
-       utf           *u;
-
-       printf("%016llx",(unsigned long long) value.l);
-
-       if (type < 0 || type > TYPE_RET)
-               printf(" <INVALID TYPE:%d>", type);
-       else
-               printf(" %s", show_jit_type_names[type]);
-
-       if (type == TYPE_ADR && value.a != NULL) {
-               obj = value.a;
-               putchar(' ');
-               utf_display_printable_ascii_classname(obj->vftbl->clazz->name);
-
-               if (obj->vftbl->clazz == class_java_lang_String) {
-                       printf(" \"");
-                       u = javastring_toutf(obj, false);
-                       utf_display_printable_ascii(u);
-                       printf("\"");
-               }
-       }
-       else if (type == TYPE_INT) {
-               printf(" %ld", (long) value.i);
-       }
-       else if (type == TYPE_LNG) {
-               printf(" %lld", (long long) value.l);
-       }
-       else if (type == TYPE_FLT) {
-               printf(" %f", value.f);
-       }
-       else if (type == TYPE_DBL) {
-               printf(" %f", value.d);
-       }
-}
-#endif /* !defined(NDEBUG) */
-
-
-#if !defined(NDEBUG)
-void replace_source_frame_println(sourceframe_t *frame)
-{
-       s4 i,j;
-       s4 t;
-
-       if (REPLACE_IS_NATIVE_FRAME(frame)) {
-               printf("\tNATIVE\n");
-               printf("\tsfi: "); replace_stackframeinfo_println(frame->sfi);
-               printf("\tnativepc: %p\n", frame->nativepc);
-               printf("\tframesize: %d\n", frame->nativeframesize);
-
-               j = 0;
-               for (i=0; i<INT_REG_CNT; ++i) {
-                       if (nregdescint[i] == REG_SAV)
-                               printf("\t%s = %p\n", abi_registers_integer_name[i], (void*)frame->nativesavint[j++]);
-               }
-
-               j = 0;
-               for (i=0; i<FLT_REG_CNT; ++i) {
-                       if (nregdescfloat[i] == REG_SAV)
-                               printf("\tF%02d = %f\n", i, frame->nativesavflt[j++]);
-               }
-
-               printf("\n");
-               return;
-       }
-
-       printf("\t");
-       method_println(frame->method);
-       printf("\tid: %d\n", frame->id);
-       printf("\ttype: %s\n", replace_type_str[frame->type]);
-       printf("\n");
-
-       if (frame->instance.a) {
-               printf("\tinstance: ");
-               java_value_print(TYPE_ADR, frame->instance);
-               printf("\n");
-       }
-
-       if (frame->javalocalcount) {
-               printf("\tlocals (%d):\n",frame->javalocalcount);
-               for (i=0; i<frame->javalocalcount; ++i) {
-                       t = frame->javalocaltype[i];
-                       if (t == TYPE_VOID) {
-                               printf("\tlocal[ %2d] = void\n",i);
-                       }
-                       else {
-                               printf("\tlocal[%c%2d] = ",TYPECHAR(t),i);
-                               java_value_print(t, frame->javalocals[i]);
-                               printf("\n");
-                       }
-               }
-               printf("\n");
-       }
-
-       if (frame->javastackdepth) {
-               printf("\tstack (depth %d):\n",frame->javastackdepth);
-               for (i=0; i<frame->javastackdepth; ++i) {
-                       t = frame->javastacktype[i];
-                       if (t == TYPE_VOID) {
-                               printf("\tstack[%2d] = void", i);
-                       }
-                       else {
-                               printf("\tstack[%2d] = ",i);
-                               java_value_print(frame->javastacktype[i], frame->javastack[i]);
-                               printf("\n");
-                       }
-               }
-               printf("\n");
-       }
-
-       if (frame->syncslotcount) {
-               printf("\tsynchronization slots (%d):\n",frame->syncslotcount);
-               for (i=0; i<frame->syncslotcount; ++i) {
-                       printf("\tslot[%2d] = ",i);
-#ifdef HAS_4BYTE_STACKSLOT
-                       printf("%08lx\n",(unsigned long) frame->syncslots[i].p);
-#else
-                       printf("%016llx\n",(unsigned long long) frame->syncslots[i].p);
-#endif
-               }
-               printf("\n");
-       }
-
-       if (frame->fromcode) {
-               printf("\tfrom %p ", (void*)frame->fromcode);
-               method_println(frame->fromcode->m);
-       }
-       if (frame->tocode) {
-               printf("\tto %p ", (void*)frame->tocode);
-               method_println(frame->tocode->m);
-       }
-
-       if (frame->fromrp) {
-               printf("\tfrom replacement point:\n");
-               replace_replacement_point_println(frame->fromrp, 2);
-       }
-       if (frame->torp) {
-               printf("\tto replacement point:\n");
-               replace_replacement_point_println(frame->torp, 2);
-       }
-
-       printf("\n");
-}
-#endif /* !defined(NDEBUG) */
-
-
-/* replace_sourcestate_println *************************************************
-   Print source state
-  
-   IN:
-       ss...............the source state to print
-  
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-void replace_sourcestate_println(sourcestate_t *ss)
-{
-       int i;
-       sourceframe_t *frame;
-
-       if (!ss) {
-               printf("(sourcestate_t *)NULL\n");
-               return;
-       }
-
-       printf("sourcestate_t:\n");
-
-       for (i=0, frame = ss->frames; frame != NULL; frame = frame->down, ++i) {
-               printf("    frame %d:\n", i);
-               replace_source_frame_println(frame);
-       }
-}
-#endif
-
-
-/* replace_sourcestate_println_short *******************************************
-
-   Print a compact representation of the given source state.
-
-   IN:
-       ss...............the source state to print
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-void replace_sourcestate_println_short(sourcestate_t *ss)
-{
-       sourceframe_t *frame;
-
-       for (frame = ss->frames; frame != NULL; frame = frame->down) {
-               printf("\t");
-
-               if (REPLACE_IS_NATIVE_FRAME(frame)) {
-                       printf("NATIVE (pc %p size %d) ",
-                                  (void*)frame->nativepc, frame->nativeframesize);
-                       replace_stackframeinfo_println(frame->sfi);
-                       continue;
-               }
-
-               if (frame->torp) {
-                       printf("%c", (frame->torp == frame->fromrp) ? '=' : '+');
-               }
-
-               printf("%s", replace_type_str[frame->fromrp->type]);
-
-               if (frame->torp && frame->torp->type != frame->fromrp->type)
-                       printf("->%s", replace_type_str[frame->torp->type]);
-
-               if (frame->tocode != frame->fromcode)
-                       printf(" (%p->%p/%d) ",
-                                  (void*) frame->fromcode, (void*) frame->tocode,
-                                  frame->fromrp->id);
-               else
-                       printf(" (%p/%d) ", (void*) frame->fromcode, frame->fromrp->id);
-
-               method_println(frame->method);
-       }
-}
-#endif
-
-#if !defined(NDEBUG)
-static void replace_stackframeinfo_println(stackframeinfo_t *sfi)
-{
-       printf("prev=%p pv=%p sp=%p ra=%p xpc=%p method=",
-                       (void*)sfi->prev, (void*)sfi->pv, (void*)sfi->sp,
-                       (void*)sfi->ra, (void*)sfi->xpc);
-
-       if (sfi->code)
-               method_println(sfi->code->m);
-       else
-               printf("(nil)\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:
- */
diff --git a/src/vm/jit/replace.cpp b/src/vm/jit/replace.cpp
new file mode 100644 (file)
index 0000000..3fec92c
--- /dev/null
@@ -0,0 +1,3593 @@
+/* src/vm/jit/replace.cpp - on-stack replacement of 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.
+
+*/
+
+
+#include "config.h"
+#include "vm/types.h"
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "arch.h"
+#include "md.h"
+
+#if defined(ENABLE_GC_CACAO)
+# include "mm/cacao-gc/gc.h"
+#endif
+
+#include "mm/dumpmemory.hpp"
+#include "mm/memory.h"
+
+#include "threads/thread.hpp"
+
+#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/executionstate.h"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/methodheader.h"
+#include "vm/jit/replace.hpp"
+#include "vm/jit/show.hpp"
+#include "vm/jit/stack.h"
+
+
+#define REPLACE_PATCH_DYNAMIC_CALL
+/*#define REPLACE_PATCH_ALL*/
+
+#if defined(ENABLE_VMLOG)
+#include <vmlog_cacao.h>
+#endif
+
+/*** architecture-dependent configuration *************************************/
+
+/* first unset the macros (default) */
+#undef REPLACE_RA_BETWEEN_FRAMES
+#undef REPLACE_RA_TOP_OF_FRAME
+#undef REPLACE_RA_LINKAGE_AREA
+#undef REPLACE_LEAFMETHODS_RA_REGISTER
+
+/* i386, x86_64 and m68k */
+#if defined(__I386__) || defined(__X86_64__) || defined(__M68K__)
+#define REPLACE_RA_BETWEEN_FRAMES
+/* alpha */
+#elif defined(__ALPHA__)
+#define REPLACE_RA_TOP_OF_FRAME
+#define REPLACE_LEAFMETHODS_RA_REGISTER
+/* powerpc */
+#elif defined(__POWERPC__)
+#define REPLACE_RA_LINKAGE_AREA
+#define REPLACE_LEAFMETHODS_RA_REGISTER
+/* s390 */
+#elif defined(__S390__)
+#define REPLACE_RA_TOP_OF_FRAME
+#endif
+
+
+/*** configuration of native stack slot size **********************************/
+
+/* XXX this should be in md-abi.h files, probably */
+
+#define SIZE_OF_STACKSLOT      8
+#define STACK_SLOTS_PER_FLOAT  1
+typedef u8 stackslot_t;
+
+
+/*** debugging ****************************************************************/
+
+#if !defined(NDEBUG)
+static void java_value_print(s4 type, replace_val_t value);
+static void replace_stackframeinfo_println(stackframeinfo_t *sfi);
+#endif
+
+#if !defined(NDEBUG)
+#define DOLOG(code)        do{ if (opt_TraceReplacement > 1) { code; } } while(0)
+#define DOLOG_SHORT(code)  do{ if (opt_TraceReplacement > 0) { code; } } while(0)
+#else
+#define DOLOG(code)
+#define DOLOG_SHORT(code)
+#endif
+
+
+/*** statistics ***************************************************************/
+
+#define REPLACE_STATISTICS
+
+#if defined(REPLACE_STATISTICS)
+
+static int stat_replacements = 0;
+static int stat_frames = 0;
+static int stat_recompile = 0;
+static int stat_staticpatch = 0;
+static int stat_unroll_inline = 0;
+static int stat_unroll_call = 0;
+static int stat_dist_frames[20] = { 0 };
+static int stat_dist_locals[20] = { 0 };
+static int stat_dist_locals_adr[10] = { 0 };
+static int stat_dist_locals_prim[10] = { 0 };
+static int stat_dist_locals_ret[10] = { 0 };
+static int stat_dist_locals_void[10] = { 0 };
+static int stat_dist_stack[10] = { 0 };
+static int stat_dist_stack_adr[10] = { 0 };
+static int stat_dist_stack_prim[10] = { 0 };
+static int stat_dist_stack_ret[10] = { 0 };
+static int stat_methods = 0;
+static int stat_rploints = 0;
+static int stat_regallocs = 0;
+static int stat_dist_method_rplpoints[20] = { 0 };
+
+#define REPLACE_COUNT(cnt)  (cnt)++
+#define REPLACE_COUNT_IF(cnt, cond)  do{ if(cond) (cnt)++; } while(0)
+#define REPLACE_COUNT_INC(cnt, inc)  ((cnt) += (inc))
+
+#define REPLACE_COUNT_DIST(array, val)                               \
+    do {                                                             \
+        int limit = (sizeof(array) / sizeof(int)) - 1;               \
+        if ((val) < (limit)) (array)[val]++;                         \
+        else (array)[limit]++;                                       \
+    } while (0)
+
+static void replace_statistics_source_frame(sourceframe_t *frame);
+
+#else
+
+#define REPLACE_COUNT(cnt)
+#define REPLACE_COUNT_IF(cnt, cond)
+#define REPLACE_COUNT_INC(cnt, inc)
+#define REPLACE_COUNT_DIST(array, val)
+
+#endif /* defined(REPLACE_STATISTICS) */
+
+
+/*** constants used internally ************************************************/
+
+#define TOP_IS_NORMAL    0
+#define TOP_IS_ON_STACK  1
+#define TOP_IS_IN_ITMP1  2
+#define TOP_IS_VOID      3
+
+
+/******************************************************************************/
+/* PART I: Creating / freeing replacement points                              */
+/******************************************************************************/
+
+
+/* replace_create_replacement_point ********************************************
+   Create a replacement point.
+  
+   IN:
+       jd...............current jitdata
+          iinfo............inlining info for the current position
+          rp...............pre-allocated (uninitialized) rplpoint
+          type.............RPLPOINT_TYPE constant
+          iptr.............current instruction
+          *pra.............current rplalloc pointer
+          javalocals.......the javalocals at the current point
+          stackvars........the stack variables at the current point
+          stackdepth.......the stack depth at the current point
+          paramcount.......number of parameters at the start of stackvars
+  
+   OUT:
+       *rpa.............points to the next free rplalloc
+  
+*******************************************************************************/
+
+static void replace_create_replacement_point(jitdata *jd,
+                                                                                        insinfo_inline *iinfo,
+                                                                                        rplpoint *rp,
+                                                                                        s4 type,
+                                                                                        instruction *iptr,
+                                                                                        rplalloc **pra,
+                                                                                        s4 *javalocals,
+                                                                                        s4 *stackvars,
+                                                                                        s4 stackdepth,
+                                                                                        s4 paramcount)
+{
+       rplalloc *ra;
+       s4        i;
+       varinfo  *v;
+       s4        index;
+
+       ra = *pra;
+
+       REPLACE_COUNT(stat_rploints);
+
+       rp->method = (iinfo) ? iinfo->method : jd->m;
+       rp->pc = NULL;        /* set by codegen */
+       rp->callsize = 0;     /* set by codegen */
+       rp->regalloc = ra;
+       rp->flags = 0;
+       rp->type = type;
+       rp->id = iptr->flags.bits >> INS_FLAG_ID_SHIFT;
+
+       /* XXX unify these two fields */
+       rp->parent = (iinfo) ? iinfo->rp : NULL;
+
+       /* store local allocation info of javalocals */
+
+       if (javalocals) {
+               for (i = 0; i < rp->method->maxlocals; ++i) {
+                       index = javalocals[i];
+                       if (index == UNUSED)
+                               continue;
+
+                       ra->index = i;
+                       if (index >= 0) {
+                               v = VAR(index);
+                               ra->flags = v->flags & (INMEMORY);
+                               ra->regoff = v->vv.regoff;
+                               ra->type = v->type;
+                       }
+                       else {
+                               ra->regoff = RETADDR_FROM_JAVALOCAL(index);
+                               ra->type = TYPE_RET;
+                               ra->flags = 0;
+                       }
+                       ra++;
+               }
+       }
+
+       /* store allocation info of java stack vars */
+
+       for (i = 0; i < stackdepth; ++i) {
+               v = VAR(stackvars[i]);
+               ra->flags = v->flags & (INMEMORY);
+               ra->index = (i < paramcount) ? RPLALLOC_PARAM : RPLALLOC_STACK;
+               ra->type  = v->type;
+               /* XXX how to handle locals on the stack containing returnAddresses? */
+               if (v->type == TYPE_RET) {
+                       assert(stackvars[i] >= jd->localcount);
+                       ra->regoff = v->vv.retaddr->nr;
+               }
+               else
+                       ra->regoff = v->vv.regoff;
+               ra++;
+       }
+
+       /* total number of allocations */
+
+       rp->regalloccount = ra - rp->regalloc;
+
+       *pra = ra;
+}
+
+
+/* replace_create_inline_start_replacement_point *******************************
+
+   Create an INLINE_START replacement point.
+
+   IN:
+       jd...............current jitdata
+          rp...............pre-allocated (uninitialized) rplpoint
+          iptr.............current instruction
+          *pra.............current rplalloc pointer
+          javalocals.......the javalocals at the current point
+
+   OUT:
+       *rpa.............points to the next free rplalloc
+
+   RETURN VALUE:
+       the insinfo_inline * for the following inlined body
+
+*******************************************************************************/
+
+static insinfo_inline * replace_create_inline_start_replacement_point(
+                                                                                        jitdata *jd,
+                                                                                        rplpoint *rp,
+                                                                                        instruction *iptr,
+                                                                                        rplalloc **pra,
+                                                                                        s4 *javalocals)
+{
+       insinfo_inline *calleeinfo;
+       rplalloc       *ra;
+
+       calleeinfo = iptr->sx.s23.s3.inlineinfo;
+
+       calleeinfo->rp = rp;
+
+       replace_create_replacement_point(jd, calleeinfo->parent, rp,
+                       RPLPOINT_TYPE_INLINE, iptr, pra,
+                       javalocals,
+                       calleeinfo->stackvars, calleeinfo->stackvarscount,
+                       calleeinfo->paramcount);
+
+       if (calleeinfo->synclocal != UNUSED) {
+               ra = (*pra)++;
+               ra->index  = RPLALLOC_SYNC;
+               ra->regoff = jd->var[calleeinfo->synclocal].vv.regoff;
+               ra->flags  = jd->var[calleeinfo->synclocal].flags & INMEMORY;
+               ra->type   = TYPE_ADR;
+
+               rp->regalloccount++;
+       }
+
+       return calleeinfo;
+}
+
+
+/* replace_create_replacement_points *******************************************
+   Create the replacement points for the given code.
+  
+   IN:
+       jd...............current jitdata, must not have any replacement points
+  
+   OUT:
+       code->rplpoints.......set to the list of replacement points
+          code->rplpointcount...number of replacement points
+          code->regalloc........list of allocation info
+          code->regalloccount...total length of allocation info list
+          code->globalcount.....number of global allocations at the
+                                start of code->regalloc
+  
+   RETURN VALUE:
+       true.............everything ok 
+       false............an exception has been thrown
+   
+*******************************************************************************/
+
+#define CLEAR_javalocals(array, method)                              \
+    do {                                                             \
+        for (i=0; i<(method)->maxlocals; ++i)                        \
+            (array)[i] = UNUSED;                                     \
+    } while (0)
+
+#define COPY_OR_CLEAR_javalocals(dest, array, method)                \
+    do {                                                             \
+        if ((array) != NULL)                                         \
+            MCOPY((dest), (array), s4, (method)->maxlocals);         \
+        else                                                         \
+            CLEAR_javalocals((dest), (method));                      \
+    } while (0)
+
+#define COUNT_javalocals(array, method, counter)                     \
+    do {                                                             \
+        for (i=0; i<(method)->maxlocals; ++i)                        \
+            if ((array)[i] != UNUSED)                                \
+                               (counter)++;                                         \
+    } while (0)
+
+bool replace_create_replacement_points(jitdata *jd)
+{
+       codeinfo        *code;
+       registerdata    *rd;
+       basicblock      *bptr;
+       int              count;
+       methodinfo      *m;
+       rplpoint        *rplpoints;
+       rplpoint        *rp;
+       int              alloccount;
+       rplalloc        *regalloc;
+       rplalloc        *ra;
+       int              i;
+       instruction     *iptr;
+       instruction     *iend;
+       s4              *javalocals;
+       s4              *jl;
+       methoddesc      *md;
+       insinfo_inline  *iinfo;
+       s4               startcount;
+       s4               firstcount;
+#if defined(REPLACE_PATCH_DYNAMIC_CALL)
+       bool             needentry;
+#endif
+
+       REPLACE_COUNT(stat_methods);
+
+       /* get required compiler data */
+
+       code = jd->code;
+       rd   = jd->rd;
+
+       /* assert that we wont overwrite already allocated data */
+
+       assert(code);
+       assert(code->m);
+       assert(code->rplpoints == NULL);
+       assert(code->rplpointcount == 0);
+       assert(code->regalloc == NULL);
+       assert(code->regalloccount == 0);
+       assert(code->globalcount == 0);
+
+       m = code->m;
+
+       /* in instance methods, we may need a rplpoint at the method entry */
+
+#if defined(REPLACE_PATCH_DYNAMIC_CALL)
+       if (!(m->flags & ACC_STATIC)) {
+               jd->basicblocks[0].bitflags |= BBFLAG_REPLACEMENT;
+               needentry = true;
+       }
+       else {
+               needentry = false;
+       }
+#endif /* defined(REPLACE_PATCH_DYNAMIC_CALL) */
+
+       /* iterate over the basic block list to find replacement points */
+
+       count = 0;
+       alloccount = 0;
+
+       javalocals = (s4*) DumpMemory::allocate(sizeof(s4) * jd->maxlocals);
+
+       for (bptr = jd->basicblocks; bptr; bptr = bptr->next) {
+
+               /* skip dead code */
+
+               if (bptr->flags < BBFINISHED)
+                       continue;
+
+               /* get info about this block */
+
+               m = bptr->method;
+               iinfo = bptr->inlineinfo;
+
+               /* initialize javalocals at the start of this block */
+
+               COPY_OR_CLEAR_javalocals(javalocals, bptr->javalocals, m);
+
+               /* iterate over the instructions */
+
+               iptr = bptr->iinstr;
+               iend = iptr + bptr->icount;
+               startcount = count;
+               firstcount = count;
+
+               for (; iptr != iend; ++iptr) {
+                       switch (iptr->opc) {
+#if defined(ENABLE_GC_CACAO)
+                               case ICMD_BUILTIN:
+                                       md = iptr->sx.s23.s3.bte->md;
+                                       count++;
+                                       COUNT_javalocals(javalocals, m, alloccount);
+                                       alloccount += iptr->s1.argcount;
+                                       if (iinfo)
+                                               alloccount -= iinfo->throughcount;
+                                       break;
+#endif
+
+                               case ICMD_INVOKESTATIC:
+                               case ICMD_INVOKESPECIAL:
+                               case ICMD_INVOKEVIRTUAL:
+                               case ICMD_INVOKEINTERFACE:
+                                       INSTRUCTION_GET_METHODDESC(iptr, md);
+                                       count++;
+                                       COUNT_javalocals(javalocals, m, alloccount);
+                                       alloccount += iptr->s1.argcount;
+                                       if (iinfo)
+                                               alloccount -= iinfo->throughcount;
+                                       break;
+
+                               case ICMD_ISTORE:
+                               case ICMD_LSTORE:
+                               case ICMD_FSTORE:
+                               case ICMD_DSTORE:
+                               case ICMD_ASTORE:
+                                       stack_javalocals_store(iptr, javalocals);
+                                       break;
+
+                               case ICMD_IRETURN:
+                               case ICMD_LRETURN:
+                               case ICMD_FRETURN:
+                               case ICMD_DRETURN:
+                               case ICMD_ARETURN:
+                                       alloccount += 1;
+                                       /* FALLTHROUGH! */
+                               case ICMD_RETURN:
+                                       count++;
+                                       break;
+
+                               case ICMD_INLINE_START:
+                                       iinfo = iptr->sx.s23.s3.inlineinfo;
+
+                                       count++;
+                                       COUNT_javalocals(javalocals, m, alloccount);
+                                       alloccount += iinfo->stackvarscount;
+                                       if (iinfo->synclocal != UNUSED)
+                                               alloccount++;
+
+                                       m = iinfo->method;
+                                       /* javalocals may be set at next block start, or now */
+                                       COPY_OR_CLEAR_javalocals(javalocals, iinfo->javalocals_start, m);
+                                       break;
+
+                               case ICMD_INLINE_BODY:
+                                       assert(iinfo == iptr->sx.s23.s3.inlineinfo);
+
+                                       jl = iinfo->javalocals_start;
+                                       if (jl == NULL) {
+                                               /* get the javalocals from the following block start */
+                                               assert(bptr->next);
+                                               jl = bptr->next->javalocals;
+                                       }
+                                       count++;
+                                       COUNT_javalocals(jl, m, alloccount);
+                                       break;
+
+                               case ICMD_INLINE_END:
+                                       assert(iinfo == iptr->sx.s23.s3.inlineinfo ||
+                                                  iinfo == iptr->sx.s23.s3.inlineinfo->parent);
+                                       iinfo = iptr->sx.s23.s3.inlineinfo;
+                                       m = iinfo->outer;
+                                       if (iinfo->javalocals_end)
+                                               MCOPY(javalocals, iinfo->javalocals_end, s4, m->maxlocals);
+                                       iinfo = iinfo->parent;
+                                       break;
+                       }
+
+                       if (iptr == bptr->iinstr)
+                               firstcount = count;
+               } /* end instruction loop */
+
+               /* create replacement points at targets of backward branches */
+               /* We only need the replacement point there, if there is no  */
+               /* replacement point inside the block.                       */
+
+               if (bptr->bitflags & BBFLAG_REPLACEMENT) {
+#if defined(REPLACE_PATCH_DYNAMIC_CALL)
+                       int test = (needentry && bptr == jd->basicblocks) ? firstcount : count;
+#else
+                       int test = count;
+#endif
+                       if (test > startcount) {
+                               /* we don't need an extra rplpoint */
+                               bptr->bitflags &= ~BBFLAG_REPLACEMENT;
+                       }
+                       else {
+                               count++;
+                               alloccount += bptr->indepth;
+                               if (bptr->inlineinfo)
+                                       alloccount -= bptr->inlineinfo->throughcount;
+
+                               COUNT_javalocals(bptr->javalocals, bptr->method, alloccount);
+                       }
+               }
+
+       } /* end basicblock loop */
+
+       /* if no points were found, there's nothing to do */
+
+       if (!count)
+               return true;
+
+       /* allocate replacement point array and allocation array */
+
+       rplpoints = MNEW(rplpoint, count);
+       regalloc = MNEW(rplalloc, alloccount);
+       ra = regalloc;
+
+       /* initialize replacement point structs */
+
+       rp = rplpoints;
+
+       /* XXX try to share code with the counting loop! */
+
+       for (bptr = jd->basicblocks; bptr; bptr = bptr->next) {
+               /* skip dead code */
+
+               if (bptr->flags < BBFINISHED)
+                       continue;
+
+               /* get info about this block */
+
+               m = bptr->method;
+               iinfo = bptr->inlineinfo;
+
+               /* initialize javalocals at the start of this block */
+
+               COPY_OR_CLEAR_javalocals(javalocals, bptr->javalocals, m);
+
+               /* create replacement points at targets of backward branches */
+
+               if (bptr->bitflags & BBFLAG_REPLACEMENT) {
+
+                       i = (iinfo) ? iinfo->throughcount : 0;
+                       replace_create_replacement_point(jd, iinfo, rp++,
+                                       bptr->type, bptr->iinstr, &ra,
+                                       bptr->javalocals, bptr->invars + i, bptr->indepth - i, 0);
+
+                       if (JITDATA_HAS_FLAG_COUNTDOWN(jd))
+                               rp[-1].flags |= RPLPOINT_FLAG_COUNTDOWN;
+               }
+
+               /* iterate over the instructions */
+
+               iptr = bptr->iinstr;
+               iend = iptr + bptr->icount;
+
+               for (; iptr != iend; ++iptr) {
+                       switch (iptr->opc) {
+#if defined(ENABLE_GC_CACAO)
+                               case ICMD_BUILTIN:
+                                       md = iptr->sx.s23.s3.bte->md;
+
+                                       i = (iinfo) ? iinfo->throughcount : 0;
+                                       replace_create_replacement_point(jd, iinfo, rp++,
+                                                       RPLPOINT_TYPE_CALL, iptr, &ra,
+                                                       javalocals, iptr->sx.s23.s2.args,
+                                                       iptr->s1.argcount - i,
+                                                       md->paramcount);
+                                       break;
+#endif
+
+                               case ICMD_INVOKESTATIC:
+                               case ICMD_INVOKESPECIAL:
+                               case ICMD_INVOKEVIRTUAL:
+                               case ICMD_INVOKEINTERFACE:
+                                       INSTRUCTION_GET_METHODDESC(iptr, md);
+
+                                       i = (iinfo) ? iinfo->throughcount : 0;
+                                       replace_create_replacement_point(jd, iinfo, rp++,
+                                                       RPLPOINT_TYPE_CALL, iptr, &ra,
+                                                       javalocals, iptr->sx.s23.s2.args,
+                                                       iptr->s1.argcount - i,
+                                                       md->paramcount);
+                                       break;
+
+                               case ICMD_ISTORE:
+                               case ICMD_LSTORE:
+                               case ICMD_FSTORE:
+                               case ICMD_DSTORE:
+                               case ICMD_ASTORE:
+                                       stack_javalocals_store(iptr, javalocals);
+                                       break;
+
+                               case ICMD_IRETURN:
+                               case ICMD_LRETURN:
+                               case ICMD_FRETURN:
+                               case ICMD_DRETURN:
+                               case ICMD_ARETURN:
+                                       replace_create_replacement_point(jd, iinfo, rp++,
+                                                       RPLPOINT_TYPE_RETURN, iptr, &ra,
+                                                       NULL, &(iptr->s1.varindex), 1, 0);
+                                       break;
+
+                               case ICMD_RETURN:
+                                       replace_create_replacement_point(jd, iinfo, rp++,
+                                                       RPLPOINT_TYPE_RETURN, iptr, &ra,
+                                                       NULL, NULL, 0, 0);
+                                       break;
+
+                               case ICMD_INLINE_START:
+                                       iinfo = replace_create_inline_start_replacement_point(
+                                                               jd, rp++, iptr, &ra, javalocals);
+                                       m = iinfo->method;
+                                       /* javalocals may be set at next block start, or now */
+                                       COPY_OR_CLEAR_javalocals(javalocals, iinfo->javalocals_start, m);
+                                       break;
+
+                               case ICMD_INLINE_BODY:
+                                       assert(iinfo == iptr->sx.s23.s3.inlineinfo);
+
+                                       jl = iinfo->javalocals_start;
+                                       if (jl == NULL) {
+                                               /* get the javalocals from the following block start */
+                                               assert(bptr->next);
+                                               jl = bptr->next->javalocals;
+                                       }
+                                       /* create a non-trappable rplpoint */
+                                       replace_create_replacement_point(jd, iinfo, rp++,
+                                                       RPLPOINT_TYPE_BODY, iptr, &ra,
+                                                       jl, NULL, 0, 0);
+                                       rp[-1].flags |= RPLPOINT_FLAG_NOTRAP;
+                                       break;
+
+                               case ICMD_INLINE_END:
+                                       assert(iinfo == iptr->sx.s23.s3.inlineinfo ||
+                                                  iinfo == iptr->sx.s23.s3.inlineinfo->parent);
+                                       iinfo = iptr->sx.s23.s3.inlineinfo;
+                                       m = iinfo->outer;
+                                       if (iinfo->javalocals_end)
+                                               MCOPY(javalocals, iinfo->javalocals_end, s4, m->maxlocals);
+                                       iinfo = iinfo->parent;
+                                       break;
+                       }
+               } /* end instruction loop */
+       } /* end basicblock loop */
+
+       assert((rp - rplpoints) == count);
+       assert((ra - regalloc) == alloccount);
+
+       /* store the data in the codeinfo */
+
+       code->rplpoints     = rplpoints;
+       code->rplpointcount = count;
+       code->regalloc      = regalloc;
+       code->regalloccount = alloccount;
+       code->globalcount   = 0;
+       code->savedintcount = INT_SAV_CNT - rd->savintreguse;
+       code->savedfltcount = FLT_SAV_CNT - rd->savfltreguse;
+#if defined(HAS_ADDRESS_REGISTER_FILE)
+       code->savedadrcount = ADR_SAV_CNT - rd->savadrreguse;
+#endif
+       code->memuse        = rd->memuse;
+       code->stackframesize = jd->cd->stackframesize;
+
+       REPLACE_COUNT_DIST(stat_dist_method_rplpoints, count);
+       REPLACE_COUNT_INC(stat_regallocs, alloccount);
+
+       /* everything alright */
+
+       return true;
+}
+
+
+/* replace_free_replacement_points *********************************************
+   Free memory used by replacement points.
+  
+   IN:
+       code.............codeinfo whose replacement points should be freed.
+  
+*******************************************************************************/
+
+void replace_free_replacement_points(codeinfo *code)
+{
+       assert(code);
+
+       if (code->rplpoints)
+               MFREE(code->rplpoints,rplpoint,code->rplpointcount);
+
+       if (code->regalloc)
+               MFREE(code->regalloc,rplalloc,code->regalloccount);
+
+       code->rplpoints = NULL;
+       code->rplpointcount = 0;
+       code->regalloc = NULL;
+       code->regalloccount = 0;
+       code->globalcount = 0;
+}
+
+
+/******************************************************************************/
+/* PART II: Activating / deactivating replacement points                      */
+/******************************************************************************/
+
+
+/* replace_activate_replacement_points *****************************************
+   Activate the replacement points of the given compilation unit. When this
+   function returns, the replacement points are "armed", so each thread
+   reaching one of the points will enter the replacement mechanism.
+   
+   IN:
+       code.............codeinfo of which replacement points should be
+                                               activated
+          mappable.........if true, only mappable replacement points are
+                                               activated
+  
+*******************************************************************************/
+
+void replace_activate_replacement_points(codeinfo *code, bool mappable)
+{
+       rplpoint *rp;
+       s4        i;
+       s4        count;
+       u1       *savedmcode;
+
+       assert(code->savedmcode == NULL);
+
+       /* count trappable replacement points */
+
+       count = 0;
+       i = code->rplpointcount;
+       rp = code->rplpoints;
+       for (; i--; rp++) {
+               if (rp->flags & RPLPOINT_FLAG_NOTRAP)
+                       continue;
+
+               if (mappable && (rp->type == RPLPOINT_TYPE_RETURN))
+                       continue;
+
+               count++;
+       }
+
+       /* allocate buffer for saved machine code */
+
+       savedmcode = MNEW(u1, count * REPLACEMENT_PATCH_SIZE);
+       code->savedmcode = savedmcode;
+       savedmcode += count * REPLACEMENT_PATCH_SIZE;
+
+       /* activate trappable replacement points */
+       /* (in reverse order to handle overlapping points within basic blocks) */
+
+       i = code->rplpointcount;
+       rp = code->rplpoints + i;
+       while (rp--, i--) {
+               assert(!(rp->flags & RPLPOINT_FLAG_ACTIVE));
+
+               if (rp->flags & RPLPOINT_FLAG_NOTRAP)
+                       continue;
+
+               if (mappable && (rp->type == RPLPOINT_TYPE_RETURN))
+                       continue;
+
+               DOLOG( printf("activate replacement point:\n");
+                          replace_replacement_point_println(rp, 1); fflush(stdout); );
+
+               savedmcode -= REPLACEMENT_PATCH_SIZE;
+
+#if defined(ENABLE_JIT)
+# if defined(ENABLE_DISASSEMBLER)
+               DOLOG( printf("\tinstruction before: ");
+                          disassinstr(rp->pc); fflush(stdout); );
+# endif
+
+               md_patch_replacement_point(rp->pc, savedmcode, false);
+
+# if defined(ENABLE_DISASSEMBLER)
+               DOLOG( printf("\tinstruction after : ");
+                          disassinstr(rp->pc); fflush(stdout); );
+# endif
+#endif
+
+               rp->flags |= RPLPOINT_FLAG_ACTIVE;
+       }
+
+       assert(savedmcode == code->savedmcode);
+}
+
+
+/* replace_deactivate_replacement_points ***************************************
+   Deactivate a replacement points in the given compilation unit.
+   When this function returns, the replacement points will be "un-armed",
+   that is a each thread reaching a point will just continue normally.
+   
+   IN:
+       code.............the compilation unit
+  
+*******************************************************************************/
+
+void replace_deactivate_replacement_points(codeinfo *code)
+{
+       rplpoint *rp;
+       s4        i;
+       s4        count;
+       u1       *savedmcode;
+
+       if (code->savedmcode == NULL) {
+               /* disarm countdown points by patching the branches */
+
+               i = code->rplpointcount;
+               rp = code->rplpoints;
+               for (; i--; rp++) {
+                       if ((rp->flags & (RPLPOINT_FLAG_ACTIVE | RPLPOINT_FLAG_COUNTDOWN))
+                                       == RPLPOINT_FLAG_COUNTDOWN)
+                       {
+#if 0
+                               *(s4*) (rp->pc + 9) = 0; /* XXX machine dependent! */
+#endif
+                       }
+               }
+               return;
+       }
+
+       assert(code->savedmcode != NULL);
+       savedmcode = code->savedmcode;
+
+       /* de-activate each trappable replacement point */
+
+       i = code->rplpointcount;
+       rp = code->rplpoints;
+       count = 0;
+       for (; i--; rp++) {
+               if (!(rp->flags & RPLPOINT_FLAG_ACTIVE))
+                       continue;
+
+               count++;
+
+               DOLOG( printf("deactivate replacement point:\n");
+                          replace_replacement_point_println(rp, 1); fflush(stdout); );
+
+#if defined(ENABLE_JIT)
+# if defined(ENABLE_DISASSEMBLER)
+               DOLOG( printf("\tinstruction before: ");
+                          disassinstr(rp->pc); fflush(stdout); );
+# endif
+
+               md_patch_replacement_point(rp->pc, savedmcode, true);
+
+# if defined(ENABLE_DISASSEMBLER)
+               DOLOG( printf("\tinstruction before: ");
+                          disassinstr(rp->pc); fflush(stdout); );
+# endif
+#endif
+
+               rp->flags &= ~RPLPOINT_FLAG_ACTIVE;
+
+               savedmcode += REPLACEMENT_PATCH_SIZE;
+       }
+
+       assert(savedmcode == code->savedmcode + count * REPLACEMENT_PATCH_SIZE);
+
+       /* free saved machine code */
+
+       MFREE(code->savedmcode, u1, count * REPLACEMENT_PATCH_SIZE);
+       code->savedmcode = NULL;
+}
+
+
+/******************************************************************************/
+/* PART III: The replacement mechanism                                        */
+/******************************************************************************/
+
+
+/* replace_read_value **********************************************************
+
+   Read a value with the given allocation from the execution state.
+   
+   IN:
+          es...............execution state
+          ra...............allocation
+          javaval..........where to put the value
+
+   OUT:
+       *javaval.........the value
+  
+*******************************************************************************/
+
+static void replace_read_value(executionstate_t *es,
+                                                          rplalloc *ra,
+                                                          replace_val_t *javaval)
+{
+       if (ra->flags & INMEMORY) {
+               /* XXX HAS_4BYTE_STACKSLOT may not be the right discriminant here */
+#ifdef HAS_4BYTE_STACKSLOT
+               if (IS_2_WORD_TYPE(ra->type)) {
+                       javaval->l = *(u8*)(es->sp + ra->regoff);
+               }
+               else {
+#endif
+                       javaval->p = *(ptrint*)(es->sp + ra->regoff);
+#ifdef HAS_4BYTE_STACKSLOT
+               }
+#endif
+       }
+       else {
+               /* allocated register */
+               if (IS_FLT_DBL_TYPE(ra->type)) {
+                       javaval->d = es->fltregs[ra->regoff];
+
+                       if (ra->type == TYPE_FLT)
+                               javaval->f = javaval->d;
+               }
+#if defined(HAS_ADDRESS_REGISTER_FILE)
+               else if (IS_ADR_TYPE(ra->type)) {
+                       javaval->p = es->adrregs[ra->regoff];
+               }
+#endif
+               else {
+#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
+                       if (ra->type == TYPE_LNG) {
+                               javaval->words.lo = es->intregs[GET_LOW_REG(ra->regoff)];
+                               javaval->words.hi = es->intregs[GET_HIGH_REG(ra->regoff)];
+                       }
+                       else
+#endif /* defined(SUPPORT_COMBINE_INTEGER_REGISTERS) */
+                               javaval->p = es->intregs[ra->regoff];
+               }
+       }
+}
+
+
+/* replace_write_value *********************************************************
+
+   Write a value to the given allocation in the execution state.
+   
+   IN:
+          es...............execution state
+          ra...............allocation
+          *javaval.........the value
+
+*******************************************************************************/
+
+static void replace_write_value(executionstate_t *es,
+                                                           rplalloc *ra,
+                                                           replace_val_t *javaval)
+{
+       if (ra->flags & INMEMORY) {
+               /* XXX HAS_4BYTE_STACKSLOT may not be the right discriminant here */
+#ifdef HAS_4BYTE_STACKSLOT
+               if (IS_2_WORD_TYPE(ra->type)) {
+                       *(u8*)(es->sp + ra->regoff) = javaval->l;
+               }
+               else {
+#endif
+                       *(ptrint*)(es->sp + ra->regoff) = javaval->p;
+#ifdef HAS_4BYTE_STACKSLOT
+               }
+#endif
+       }
+       else {
+               /* allocated register */
+               switch (ra->type) {
+                       case TYPE_FLT:
+                               es->fltregs[ra->regoff] = (double) javaval->f;
+                               break;
+                       case TYPE_DBL:
+                               es->fltregs[ra->regoff] = javaval->d;
+                               break;
+#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
+                       case TYPE_LNG:
+                               es->intregs[GET_LOW_REG(ra->regoff)] = javaval->words.lo;
+                               es->intregs[GET_HIGH_REG(ra->regoff)] = javaval->words.hi;
+                               break;
+#endif
+#if defined(HAS_ADDRESS_REGISTER_FILE)
+                       case TYPE_ADR:
+                               es->adrregs[ra->regoff] = javaval->p;
+#endif
+                       default:
+                               es->intregs[ra->regoff] = javaval->p;
+               }
+       }
+}
+
+
+/* replace_new_sourceframe *****************************************************
+
+   Allocate a new source frame and insert it at the front of the frame list.
+   
+   IN:
+          ss...............the source state
+
+   OUT:
+          ss->frames.......set to new frame (the new head of the frame list).
+
+   RETURN VALUE:
+       returns the new frame
+
+*******************************************************************************/
+
+static sourceframe_t *replace_new_sourceframe(sourcestate_t *ss)
+{
+       sourceframe_t *frame;
+
+       frame = (sourceframe_t*) DumpMemory::allocate(sizeof(sourceframe_t));
+       MZERO(frame, sourceframe_t, 1);
+
+       frame->down = ss->frames;
+       ss->frames = frame;
+
+       return frame;
+}
+
+
+/* replace_read_executionstate *************************************************
+
+   Read a source frame from the given executions state.
+   The new source frame is pushed to the front of the frame list of the
+   source state.
+
+   IN:
+       rp...............replacement point at which `es` was taken
+          es...............execution state
+          ss...............the source state to add the source frame to
+          topframe.........true, if the first (top-most) source frame on the
+                           stack is to be read
+
+   OUT:
+       *ss..............the source state with the newly created source frame
+                           added
+  
+*******************************************************************************/
+
+static s4 replace_normalize_type_map[] = {
+/* RPLPOINT_TYPE_STD    |--> */ RPLPOINT_TYPE_STD,
+/* RPLPOINT_TYPE_EXH    |--> */ RPLPOINT_TYPE_STD,
+/* RPLPOINT_TYPE_SBR    |--> */ RPLPOINT_TYPE_STD,
+/* RPLPOINT_TYPE_CALL   |--> */ RPLPOINT_TYPE_CALL,
+/* RPLPOINT_TYPE_INLINE |--> */ RPLPOINT_TYPE_CALL,
+/* RPLPOINT_TYPE_RETURN |--> */ RPLPOINT_TYPE_RETURN,
+/* RPLPOINT_TYPE_BODY   |--> */ RPLPOINT_TYPE_STD
+};
+
+
+static void replace_read_executionstate(rplpoint *rp,
+                                                                               executionstate_t *es,
+                                                                               sourcestate_t *ss,
+                                                                               bool topframe)
+{
+       methodinfo    *m;
+       codeinfo      *code;
+       int            count;
+       int            i;
+       rplalloc      *ra;
+       sourceframe_t *frame;
+       int            topslot;
+       stackslot_t   *sp;
+       stackslot_t   *basesp;
+
+       code = code_find_codeinfo_for_pc(rp->pc);
+       m = rp->method;
+       topslot = TOP_IS_NORMAL;
+
+       /* stack pointer */
+
+       sp = (stackslot_t *) es->sp;
+
+       /* in some cases the top stack slot is passed in REG_ITMP1 */
+
+       if (rp->type == BBTYPE_EXH) {
+               topslot = TOP_IS_IN_ITMP1;
+       }
+
+       /* calculate base stack pointer */
+
+       basesp = sp + code->stackframesize;
+
+       /* create the source frame */
+
+       frame = replace_new_sourceframe(ss);
+       frame->method = rp->method;
+       frame->id = rp->id;
+       assert(rp->type >= 0 && rp->type < sizeof(replace_normalize_type_map)/sizeof(s4));
+       frame->type = replace_normalize_type_map[rp->type];
+       frame->fromrp = rp;
+       frame->fromcode = code;
+
+       /* read local variables */
+
+       count = m->maxlocals;
+       frame->javalocalcount = count;
+       frame->javalocals = (replace_val_t*) DumpMemory::allocate(sizeof(replace_val_t) * count);
+       frame->javalocaltype = (u1*) DumpMemory::allocate(sizeof(u1) * count);
+
+       /* mark values as undefined */
+       for (i=0; i<count; ++i) {
+#if !defined(NDEBUG)
+               frame->javalocals[i].l = (u8) 0x00dead0000dead00ULL;
+#endif
+               frame->javalocaltype[i] = TYPE_VOID;
+       }
+
+       /* some entries in the intregs array are not meaningful */
+       /*es->intregs[REG_ITMP3] = (u8) 0x11dead1111dead11ULL;*/
+#if !defined(NDEBUG)
+       es->intregs[REG_SP   ] = (ptrint) 0x11dead1111dead11ULL;
+#ifdef REG_PV
+       es->intregs[REG_PV   ] = (ptrint) 0x11dead1111dead11ULL;
+#endif
+#endif /* !defined(NDEBUG) */
+
+       /* read javalocals */
+
+       count = rp->regalloccount;
+       ra = rp->regalloc;
+
+       while (count && (i = ra->index) >= 0) {
+               assert(i < m->maxlocals);
+               frame->javalocaltype[i] = ra->type;
+               if (ra->type == TYPE_RET)
+                       frame->javalocals[i].i = ra->regoff;
+               else
+                       replace_read_value(es, ra, frame->javalocals + i);
+               ra++;
+               count--;
+       }
+
+       /* read instance, if this is the first rplpoint */
+
+#if defined(REPLACE_PATCH_DYNAMIC_CALL)
+       if (topframe && !(rp->method->flags & ACC_STATIC) && rp == code->rplpoints) {
+#if 1
+               /* we are at the start of the method body, so if local 0 is set, */
+               /* it is the instance.                                           */
+               if (frame->javalocaltype[0] == TYPE_ADR)
+                       frame->instance = frame->javalocals[0];
+#else
+               rplalloc instra;
+               methoddesc *md;
+
+               md = rp->method->parseddesc;
+               assert(md->params);
+               assert(md->paramcount >= 1);
+               instra.type = TYPE_ADR;
+               instra.regoff = md->params[0].regoff;
+               if (md->params[0].inmemory) {
+                       instra.flags = INMEMORY;
+                       instra.regoff += (1 + code->stackframesize) * SIZE_OF_STACKSLOT;
+               }
+               else {
+                       instra.flags = 0;
+               }
+               replace_read_value(es, &instra, &(frame->instance));
+#endif
+       }
+#if defined(__I386__)
+       else if (!(rp->method->flags & ACC_STATIC)) {
+               /* On i386 we always pass the first argument on stack. */
+               frame->instance.a = *(java_object_t **)(basesp + 1);
+       } 
+#endif
+#endif /* defined(REPLACE_PATCH_DYNAMIC_CALL) */
+
+       /* read stack slots */
+
+       frame->javastackdepth = count;
+       frame->javastack = (replace_val_t*) DumpMemory::allocate(sizeof(replace_val_t) * count);
+       frame->javastacktype = (u1*) DumpMemory::allocate(sizeof(u1) * count);
+
+#if !defined(NDEBUG)
+       /* mark values as undefined */
+       for (i=0; i<count; ++i) {
+               frame->javastack[i].l = (u8) 0x00dead0000dead00ULL;
+               frame->javastacktype[i] = TYPE_VOID;
+       }
+#endif /* !defined(NDEBUG) */
+
+       i = 0;
+
+       /* the first stack slot is special in SBR and EXH blocks */
+
+       if (topslot == TOP_IS_ON_STACK) {
+               assert(count);
+
+               assert(ra->index == RPLALLOC_STACK);
+               assert(ra->type == TYPE_ADR);
+               frame->javastack[i].p = sp[-1];
+               frame->javastacktype[i] = TYPE_ADR; /* XXX RET */
+               count--;
+               i++;
+               ra++;
+       }
+       else if (topslot == TOP_IS_IN_ITMP1) {
+               assert(count);
+
+               assert(ra->index == RPLALLOC_STACK);
+               assert(ra->type == TYPE_ADR);
+               frame->javastack[i].p = es->intregs[REG_ITMP1];
+               frame->javastacktype[i] = TYPE_ADR; /* XXX RET */
+               count--;
+               i++;
+               ra++;
+       }
+       else if (topslot == TOP_IS_VOID) {
+               assert(count);
+
+               assert(ra->index == RPLALLOC_STACK);
+               frame->javastack[i].l = 0;
+               frame->javastacktype[i] = TYPE_VOID;
+               count--;
+               i++;
+               ra++;
+       }
+
+       /* read remaining stack slots */
+
+       for (; count--; ra++) {
+               if (ra->index == RPLALLOC_SYNC) {
+                       assert(rp->type == RPLPOINT_TYPE_INLINE);
+
+                       /* only read synchronization slots when traversing an inline point */
+
+                       if (!topframe) {
+                               sourceframe_t *calleeframe = frame->down;
+                               assert(calleeframe);
+                               assert(calleeframe->syncslotcount == 0);
+                               assert(calleeframe->syncslots == NULL);
+
+                               calleeframe->syncslotcount = 1;
+                               calleeframe->syncslots = (replace_val_t*) DumpMemory::allocate(sizeof(replace_val_t));
+                               replace_read_value(es,ra,calleeframe->syncslots);
+                       }
+
+                       frame->javastackdepth--;
+                       continue;
+               }
+
+               assert(ra->index == RPLALLOC_STACK || ra->index == RPLALLOC_PARAM);
+
+               /* do not read parameters of calls down the call chain */
+
+               if (!topframe && ra->index == RPLALLOC_PARAM) {
+                       frame->javastackdepth--;
+               }
+               else {
+                       if (ra->type == TYPE_RET)
+                               frame->javastack[i].i = ra->regoff;
+                       else
+                               replace_read_value(es,ra,frame->javastack + i);
+                       frame->javastacktype[i] = ra->type;
+                       i++;
+               }
+       }
+}
+
+
+/* replace_write_executionstate ************************************************
+
+   Pop a source frame from the front of the frame list of the given source state
+   and write its values into the execution state.
+
+   IN:
+       rp...............replacement point for which execution state should be
+                           created
+          es...............the execution state to modify
+          ss...............the given source state
+          topframe.........true, if this is the last (top-most) source frame to be
+                           translated
+
+   OUT:
+       *es..............the execution state derived from the source state
+  
+*******************************************************************************/
+
+static void replace_write_executionstate(rplpoint *rp,
+                                                                                executionstate_t *es,
+                                                                                sourcestate_t *ss,
+                                                                                bool topframe)
+{
+       methodinfo     *m;
+       codeinfo       *code;
+       int             count;
+       int             i;
+       rplalloc       *ra;
+       sourceframe_t  *frame;
+       int             topslot;
+       stackslot_t    *sp;
+       stackslot_t    *basesp;
+
+       code = code_find_codeinfo_for_pc(rp->pc);
+       m = rp->method;
+       topslot = TOP_IS_NORMAL;
+
+       /* pop a source frame */
+
+       frame = ss->frames;
+       assert(frame);
+       ss->frames = frame->down;
+
+       /* calculate stack pointer */
+
+       sp = (stackslot_t *) es->sp;
+
+       basesp = sp + code->stackframesize;
+
+       /* in some cases the top stack slot is passed in REG_ITMP1 */
+
+       if (rp->type == BBTYPE_EXH) {
+               topslot = TOP_IS_IN_ITMP1;
+       }
+
+       /* write javalocals */
+
+       ra = rp->regalloc;
+       count = rp->regalloccount;
+
+       while (count && (i = ra->index) >= 0) {
+               assert(i < m->maxlocals);
+               assert(i < frame->javalocalcount);
+               assert(ra->type == frame->javalocaltype[i]);
+               if (ra->type == TYPE_RET) {
+                       /* XXX assert that it matches this rplpoint */
+               }
+               else
+                       replace_write_value(es, ra, frame->javalocals + i);
+               count--;
+               ra++;
+       }
+
+       /* write stack slots */
+
+       i = 0;
+
+       /* the first stack slot is special in SBR and EXH blocks */
+
+       if (topslot == TOP_IS_ON_STACK) {
+               assert(count);
+
+               assert(ra->index == RPLALLOC_STACK);
+               assert(i < frame->javastackdepth);
+               assert(frame->javastacktype[i] == TYPE_ADR);
+               sp[-1] = frame->javastack[i].p;
+               count--;
+               i++;
+               ra++;
+       }
+       else if (topslot == TOP_IS_IN_ITMP1) {
+               assert(count);
+
+               assert(ra->index == RPLALLOC_STACK);
+               assert(i < frame->javastackdepth);
+               assert(frame->javastacktype[i] == TYPE_ADR);
+               es->intregs[REG_ITMP1] = frame->javastack[i].p;
+               count--;
+               i++;
+               ra++;
+       }
+       else if (topslot == TOP_IS_VOID) {
+               assert(count);
+
+               assert(ra->index == RPLALLOC_STACK);
+               assert(i < frame->javastackdepth);
+               assert(frame->javastacktype[i] == TYPE_VOID);
+               count--;
+               i++;
+               ra++;
+       }
+
+       /* write remaining stack slots */
+
+       for (; count--; ra++) {
+               if (ra->index == RPLALLOC_SYNC) {
+                       assert(rp->type == RPLPOINT_TYPE_INLINE);
+
+                       /* only write synchronization slots when traversing an inline point */
+
+                       if (!topframe) {
+                               assert(frame->down);
+                               assert(frame->down->syncslotcount == 1); /* XXX need to understand more cases */
+                               assert(frame->down->syncslots != NULL);
+
+                               replace_write_value(es,ra,frame->down->syncslots);
+                       }
+                       continue;
+               }
+
+               assert(ra->index == RPLALLOC_STACK || ra->index == RPLALLOC_PARAM);
+
+               /* do not write parameters of calls down the call chain */
+
+               if (!topframe && ra->index == RPLALLOC_PARAM) {
+                       /* skip it */
+                       /*
+                       ra->index = RPLALLOC_PARAM;
+                       replace_val_t v;
+                       v.l = 0;
+                       replace_write_value(es,ra,&v);
+                       */
+               }
+               else {
+                       assert(i < frame->javastackdepth);
+                       assert(ra->type == frame->javastacktype[i]);
+                       if (ra->type == TYPE_RET) {
+                               /* XXX assert that it matches this rplpoint */
+                       }
+                       else {
+                               replace_write_value(es,ra,frame->javastack + i);
+                       }
+                       i++;
+               }
+       }
+
+       /* set new pc */
+
+       es->pc = rp->pc;
+}
+
+
+/* md_pop_stackframe ***********************************************************
+
+   Restore callee-saved registers (including the RA register),
+   set the stack pointer to the next stackframe,
+   set the PC to the return address of the popped frame.
+
+   *** This function imitates the effects of the method epilog ***
+   *** and returning from the method call.                     ***
+
+   IN:
+       es...............execution state
+
+   OUT:
+       *es..............the execution state after popping the stack frame
+                        NOTE: es->code and es->pv are NOT updated.
+
+*******************************************************************************/
+
+void md_pop_stackframe(executionstate_t *es)
+{
+       u1 *ra;
+       s4 ra_align_off;
+       s4 reg;
+       s4 i;
+       stackslot_t *basesp;
+       stackslot_t *sp;
+
+       assert(es->code);
+
+       /* alignment offset of RA */
+
+       ra_align_off = 0;
+#if defined(REPLACE_RA_BETWEEN_FRAMES)
+    if (es->code->stackframesize)
+               ra_align_off = SIZE_OF_STACKSLOT - SIZEOF_VOID_P;
+#endif
+
+       /* read the return address */
+
+#if defined(REPLACE_LEAFMETHODS_RA_REGISTER)
+       if (code_is_leafmethod(es->code))
+               ra = es->ra;
+       else
+#endif
+               ra = (u1*) md_stacktrace_get_returnaddress(es->sp,
+                          SIZE_OF_STACKSLOT * es->code->stackframesize + ra_align_off);
+
+       /* calculate the base of the stack frame */
+
+       sp = (stackslot_t *) es->sp;
+       basesp = sp + es->code->stackframesize;
+
+       /* restore return address, if part of frame */
+
+#if defined(REPLACE_RA_TOP_OF_FRAME)
+#if defined(REPLACE_LEAFMETHODS_RA_REGISTER)
+       if (!code_is_leafmethod(es->code))
+#endif
+               es->ra = (u1*) (ptrint) *--basesp;
+#endif /* REPLACE_RA_TOP_OF_FRAME */
+
+#if defined(REPLACE_RA_LINKAGE_AREA)
+#if defined(REPLACE_LEAFMETHODS_RA_REGISTER)
+       if (!code_is_leafmethod(es->code))
+#endif
+               es->ra = (u1*) (ptrint) basesp[LA_LR_OFFSET / sizeof(stackslot_t)];
+#endif /* REPLACE_RA_LINKAGE_AREA */
+
+       /* restore saved int registers */
+
+       reg = INT_REG_CNT;
+       for (i=0; i<es->code->savedintcount; ++i) {
+               while (nregdescint[--reg] != REG_SAV)
+                       ;
+               es->intregs[reg] = *--basesp;
+       }
+
+       /* restore saved flt registers */
+
+       /* XXX align? */
+       reg = FLT_REG_CNT;
+       for (i=0; i<es->code->savedfltcount; ++i) {
+               while (nregdescfloat[--reg] != REG_SAV)
+                       ;
+               basesp -= STACK_SLOTS_PER_FLOAT;
+               es->fltregs[reg] = *(double*)basesp;
+       }
+
+#if defined(HAS_ADDRESS_REGISTER_FILE)
+       /* restore saved adr registers */
+
+       reg = ADR_REG_CNT;
+       for (i=0; i<es->code->savedadrcount; ++i) {
+               while (nregdescadr[--reg] != REG_SAV)
+                       ;
+               es->adrregs[reg] = *--basesp;
+       }
+#endif
+
+       /* adjust the stackpointer */
+
+       es->sp += SIZE_OF_STACKSLOT * es->code->stackframesize;
+
+#if defined(REPLACE_RA_BETWEEN_FRAMES)
+       es->sp += ra_align_off + SIZEOF_VOID_P; /* skip return address */
+#endif
+
+       /* set the program counter to the return address */
+
+       es->pc = ra;
+
+       /* in debugging mode clobber non-saved registers */
+
+#if !defined(NDEBUG)
+       /* for debugging */
+       for (i=0; i<INT_REG_CNT; ++i)
+               if (nregdescint[i] != REG_SAV)
+                       es->intregs[i] = (ptrint) 0x33dead3333dead33ULL;
+       for (i=0; i<FLT_REG_CNT; ++i)
+               if (nregdescfloat[i] != REG_SAV)
+                       *(u8*)&(es->fltregs[i]) = 0x33dead3333dead33ULL;
+# if defined(HAS_ADDRESS_REGISTER_FILE)
+       for (i=0; i<ADR_REG_CNT; ++i)
+               if (nregdescadr[i] != REG_SAV)
+                       es->adrregs[i] = (ptrint) 0x33dead3333dead33ULL;
+# endif
+#endif /* !defined(NDEBUG) */
+}
+
+
+/* md_push_stackframe **********************************************************
+
+   Save the given return address, build the new stackframe,
+   and store callee-saved registers.
+
+   *** This function imitates the effects of a call and the ***
+   *** method prolog of the callee.                         ***
+
+   IN:
+       es...............execution state
+       calleecode.......the code we are "calling"
+       ra...............the return address to save
+
+   OUT:
+       *es..............the execution state after pushing the stack frame
+                        NOTE: es->pc, es->code, and es->pv are NOT updated.
+
+*******************************************************************************/
+
+void md_push_stackframe(executionstate_t *es, codeinfo *calleecode, u1 *ra)
+{
+       s4           reg;
+       s4           i;
+       stackslot_t *basesp;
+       stackslot_t *sp;
+
+       assert(es);
+       assert(calleecode);
+
+       /* write the return address */
+
+#if defined(REPLACE_RA_BETWEEN_FRAMES)
+       es->sp -= SIZEOF_VOID_P;
+       *((void **)es->sp) = (void *) ra;
+       if (calleecode->stackframesize)
+               es->sp -= (SIZE_OF_STACKSLOT - SIZEOF_VOID_P);
+#endif /* REPLACE_RA_BETWEEN_FRAMES */
+
+       es->ra = (u1*) (ptrint) ra;
+
+       /* build the stackframe */
+
+       DOLOG( printf("building stackframe of %d words at %p\n",
+                                 calleecode->stackframesize, (void*)es->sp); );
+
+       sp = (stackslot_t *) es->sp;
+       basesp = sp;
+
+       sp -= calleecode->stackframesize;
+       es->sp = (u1*) sp;
+
+       /* in debug mode, invalidate stack frame first */
+
+       /* XXX may not invalidate linkage area used by native code! */
+
+#if !defined(NDEBUG) && 0
+       for (i=0; i< (basesp - sp) && i < 1; ++i) {
+               sp[i] = 0xdeaddeadU;
+       }
+#endif
+
+#if defined(__I386__)
+       /* Stackslot 0 may contain the object instance for vftbl patching.
+          Destroy it, so there's no undefined value used. */
+       if ((basesp - sp) > 0) {
+               sp[0] = 0;
+       }
+#endif
+
+       /* save the return address register */
+
+#if defined(REPLACE_RA_TOP_OF_FRAME)
+#if defined(REPLACE_LEAFMETHODS_RA_REGISTER)
+       if (!code_is_leafmethod(calleecode))
+#endif
+               *--basesp = (ptrint) ra;
+#endif /* REPLACE_RA_TOP_OF_FRAME */
+
+#if defined(REPLACE_RA_LINKAGE_AREA)
+#if defined(REPLACE_LEAFMETHODS_RA_REGISTER)
+       if (!code_is_leafmethod(calleecode))
+#endif
+               basesp[LA_LR_OFFSET / sizeof(stackslot_t)] = (ptrint) ra;
+#endif /* REPLACE_RA_LINKAGE_AREA */
+
+       /* save int registers */
+
+       reg = INT_REG_CNT;
+       for (i=0; i<calleecode->savedintcount; ++i) {
+               while (nregdescint[--reg] != REG_SAV)
+                       ;
+               *--basesp = es->intregs[reg];
+
+               /* XXX may not clobber saved regs used by native code! */
+#if !defined(NDEBUG) && 0
+               es->intregs[reg] = (ptrint) 0x44dead4444dead44ULL;
+#endif
+       }
+
+       /* save flt registers */
+
+       /* XXX align? */
+       reg = FLT_REG_CNT;
+       for (i=0; i<calleecode->savedfltcount; ++i) {
+               while (nregdescfloat[--reg] != REG_SAV)
+                       ;
+               basesp -= STACK_SLOTS_PER_FLOAT;
+               *(double*)basesp = es->fltregs[reg];
+
+               /* XXX may not clobber saved regs used by native code! */
+#if !defined(NDEBUG) && 0
+               *(u8*)&(es->fltregs[reg]) = 0x44dead4444dead44ULL;
+#endif
+       }
+
+#if defined(HAS_ADDRESS_REGISTER_FILE)
+       /* save adr registers */
+
+       reg = ADR_REG_CNT;
+       for (i=0; i<calleecode->savedadrcount; ++i) {
+               while (nregdescadr[--reg] != REG_SAV)
+                       ;
+               *--basesp = es->adrregs[reg];
+
+               /* XXX may not clobber saved regs used by native code! */
+#if !defined(NDEBUG) && 0
+               es->adrregs[reg] = (ptrint) 0x44dead4444dead44ULL;
+#endif
+       }
+#endif
+}
+
+
+/* replace_pop_activation_record ***********************************************
+
+   Peel a stack frame from the execution state.
+
+   *** This function imitates the effects of the method epilog ***
+   *** and returning from the method call.                     ***
+
+   IN:
+       es...............execution state
+       frame............source frame, receives synchronization slots
+
+   OUT:
+       *es..............the execution state after popping the stack frame
+
+   RETURN VALUE:
+       the return address of the poped activation record
+
+*******************************************************************************/
+
+u1* replace_pop_activation_record(executionstate_t *es,
+                                                                 sourceframe_t *frame)
+{
+       u1 *ra;
+       s4 i;
+       s4 count;
+       codeinfo *code;
+       stackslot_t *sp;
+
+       assert(es->code);
+       assert(frame);
+
+       /* calculate the base of the stack frame */
+
+       sp = (stackslot_t *) es->sp;
+       assert(frame->syncslotcount == 0);
+       assert(frame->syncslots == NULL);
+       count = code_get_sync_slot_count(es->code);
+       frame->syncslotcount = count;
+       frame->syncslots = (replace_val_t*) DumpMemory::allocate(sizeof(replace_val_t) * count);
+       for (i=0; i<count; ++i) {
+               frame->syncslots[i].p = sp[es->code->memuse + i]; /* XXX md_ function */
+       }
+
+       /* pop the stackframe */
+
+       md_pop_stackframe(es);
+
+       ra = es->pc;
+
+       DOLOG( printf("RA = %p\n", (void*)ra); );
+
+       /* Subtract one from the PC so we do not hit the replacement point */
+       /* of the instruction following the call, if there is one.         */
+
+       es->pc--;
+
+       /* find the new codeinfo */
+
+       void* pv = md_codegen_get_pv_from_pc(ra);
+       DOLOG( printf("PV = %p\n", pv); );
+
+       code = code_get_codeinfo_for_pv(pv);
+       DOLOG( printf("CODE = %p\n", (void*) code); );
+
+       /* return NULL if we reached native code */
+
+       es->pv   = (uint8_t*) pv;
+       es->code = code;
+
+       return (code) ? ra : NULL;
+}
+
+
+/* replace_patch_method_pointer ************************************************
+
+   Patch a method pointer (may be in code, data segment, vftbl, or interface
+   table).
+
+   IN:
+          mpp..............address of the method pointer to patch
+          entrypoint.......the new entrypoint of the method
+          kind.............kind of call to patch, used only for debugging
+
+*******************************************************************************/
+
+static void replace_patch_method_pointer(methodptr *mpp,
+                                                                                methodptr entrypoint,
+                                                                                const char *kind)
+{
+#if !defined(NDEBUG)
+       codeinfo       *oldcode;
+       codeinfo       *newcode;
+#endif
+
+       DOLOG( printf("patch method pointer from: %p to %p\n",
+                                 (void*) *mpp, (void*)entrypoint); );
+
+#if !defined(NDEBUG)
+       oldcode = code_get_codeinfo_for_pv(*mpp);
+       newcode = code_get_codeinfo_for_pv(entrypoint);
+
+       DOLOG_SHORT( printf("\tpatch %s %p ", kind, (void*) oldcode);
+                                method_println(oldcode->m);
+                                printf("\t      with      %p ", (void*) newcode);
+                                method_println(newcode->m); );
+
+       assert(oldcode->m == newcode->m);
+#endif
+
+       /* write the new entrypoint */
+
+       *mpp = (methodptr) entrypoint;
+}
+
+
+/* replace_patch_class *********************************************************
+
+   Patch a method in the given class.
+
+   IN:
+          vftbl............vftbl of the class
+          m................the method to patch
+          oldentrypoint....the old entrypoint to replace
+          entrypoint.......the new entrypoint
+
+*******************************************************************************/
+
+void replace_patch_class(vftbl_t *vftbl,
+                                                methodinfo *m,
+                                                u1 *oldentrypoint,
+                                                u1 *entrypoint)
+{
+       s4                 i;
+       methodptr         *mpp;
+       methodptr         *mppend;
+
+       /* patch the vftbl of the class */
+
+       replace_patch_method_pointer(vftbl->table + m->vftblindex,
+                                                                entrypoint,
+                                                                "virtual  ");
+
+       /* patch the interface tables */
+
+       assert(oldentrypoint);
+
+       for (i=0; i < vftbl->interfacetablelength; ++i) {
+               mpp = vftbl->interfacetable[-i];
+               mppend = mpp + vftbl->interfacevftbllength[i];
+               for (; mpp != mppend; ++mpp)
+                       if (*mpp == oldentrypoint) {
+                               replace_patch_method_pointer(mpp, entrypoint, "interface");
+                       }
+       }
+}
+
+
+/* replace_patch_class_hierarchy ***********************************************
+
+   Patch a method in all loaded classes.
+
+   IN:
+          m................the method to patch
+          oldentrypoint....the old entrypoint to replace
+          entrypoint.......the new entrypoint
+
+*******************************************************************************/
+
+struct replace_patch_data_t {
+       methodinfo *m;
+       u1         *oldentrypoint;
+       u1         *entrypoint;
+};
+
+void replace_patch_callback(classinfo *c, struct replace_patch_data_t *pd)
+{
+       vftbl_t *vftbl = c->vftbl;
+
+       if (vftbl != NULL
+               && vftbl->vftbllength > pd->m->vftblindex
+               && (void*) vftbl->table[pd->m->vftblindex] != (void*) (uintptr_t) &asm_abstractmethoderror
+               && code_get_methodinfo_for_pv(vftbl->table[pd->m->vftblindex]) == pd->m)
+       {
+               replace_patch_class(c->vftbl, pd->m, pd->oldentrypoint, pd->entrypoint);
+       }
+}
+
+void replace_patch_class_hierarchy(methodinfo *m,
+                                                                  u1 *oldentrypoint,
+                                                                  u1 *entrypoint)
+{
+       struct replace_patch_data_t pd;
+
+       pd.m = m;
+       pd.oldentrypoint = oldentrypoint;
+       pd.entrypoint = entrypoint;
+
+       DOLOG_SHORT( printf("patching class hierarchy: ");
+                            method_println(m); );
+
+       classcache_foreach_loaded_class(
+                       (classcache_foreach_functionptr_t) &replace_patch_callback,
+                       (void*) &pd);
+}
+
+
+/* replace_patch_future_calls **************************************************
+
+   Analyse a call site and depending on the kind of call patch the call, the
+   virtual function table, or the interface table.
+
+   IN:
+          ra...............return address pointing after the call site
+          callerframe......source frame of the caller
+          calleeframe......source frame of the callee, must have been mapped
+
+*******************************************************************************/
+
+void replace_patch_future_calls(u1 *ra,
+                                                               sourceframe_t *callerframe,
+                                                               sourceframe_t *calleeframe)
+{
+       u1            *patchpos;
+       methodptr      entrypoint;
+       methodptr      oldentrypoint;
+       bool           atentry;
+       void          *pv;
+       codeinfo      *calleecode;
+       methodinfo    *calleem;
+       java_object_t *obj;
+       vftbl_t       *vftbl;
+
+       assert(ra);
+       assert(callerframe->down == calleeframe);
+
+       /* get the new codeinfo and the method that shall be entered */
+
+       calleecode = calleeframe->tocode;
+       assert(calleecode);
+
+       calleem = calleeframe->method;
+       assert(calleem == calleecode->m);
+
+       entrypoint = (methodptr) calleecode->entrypoint;
+
+       /* check if we are at an method entry rplpoint at the innermost frame */
+
+       atentry = (calleeframe->down == NULL)
+                       && !(calleem->flags & ACC_STATIC)
+                       && (calleeframe->fromrp->id == 0); /* XXX */
+
+       /* get the position to patch, in case it was a statically bound call   */
+
+       pv = callerframe->fromcode->entrypoint;
+       patchpos = (u1*) md_jit_method_patch_address(pv, ra, NULL);
+
+       if (patchpos == NULL) {
+               /* the call was dispatched dynamically */
+
+               /* we can only patch such calls if we are at the entry point */
+
+#if !defined(__I386__)
+               /* On i386 we always know the instance argument. */
+               if (!atentry)
+                       return;
+#endif
+
+               assert((calleem->flags & ACC_STATIC) == 0);
+
+               oldentrypoint = calleeframe->fromcode->entrypoint;
+
+               /* we need to know the instance */
+
+               if (!calleeframe->instance.a) {
+                       DOLOG_SHORT( printf("WARNING: object instance unknown!\n"); );
+                       replace_patch_class_hierarchy(calleem, oldentrypoint, entrypoint);
+                       return;
+               }
+
+               /* get the vftbl */
+
+               obj = calleeframe->instance.a;
+               vftbl = obj->vftbl;
+
+               assert(vftbl->clazz->vftbl == vftbl);
+
+               DOLOG_SHORT( printf("\tclass: "); class_println(vftbl->clazz); );
+
+               replace_patch_class(vftbl, calleem, oldentrypoint, entrypoint);
+       }
+       else {
+               /* the call was statically bound */
+
+#if defined(__I386__)
+               /* It happens that there is a patcher trap. (pm) */
+               if (*(u2 *)(patchpos - 1) == 0x0b0f) {
+               } else
+#endif
+               replace_patch_method_pointer((methodptr *) patchpos, entrypoint, "static   ");
+       }
+}
+
+
+/* replace_push_activation_record **********************************************
+
+   Push a stack frame onto the execution state.
+   
+   *** This function imitates the effects of a call and the ***
+   *** method prolog of the callee.                         ***
+
+   IN:
+          es...............execution state
+          rpcall...........the replacement point at the call site
+          callerframe......source frame of the caller, or NULL for creating the
+                           first frame
+          calleeframe......source frame of the callee, must have been mapped
+
+   OUT:
+       *es..............the execution state after pushing the stack frame
+  
+*******************************************************************************/
+
+void replace_push_activation_record(executionstate_t *es,
+                                                                       rplpoint *rpcall,
+                                                                       sourceframe_t *callerframe,
+                                                                       sourceframe_t *calleeframe)
+{
+       s4           i;
+       s4           count;
+       stackslot_t *sp;
+       u1          *ra;
+       codeinfo    *calleecode;
+
+       assert(es);
+       assert(!rpcall || callerframe);
+    assert(!rpcall || rpcall->type == RPLPOINT_TYPE_CALL);
+       assert(!rpcall || rpcall == callerframe->torp);
+       assert(calleeframe);
+       assert(!callerframe || calleeframe == callerframe->down);
+
+       /* the compilation unit we are entering */
+
+       calleecode = calleeframe->tocode;
+       assert(calleecode);
+
+       /* calculate the return address */
+
+       if (rpcall)
+               ra = rpcall->pc + rpcall->callsize;
+       else
+               ra = es->pc + 1 /* XXX this is ugly */;
+
+       /* push the stackframe */
+
+       md_push_stackframe(es, calleecode, ra);
+
+       /* we move into a new code unit, set code, PC, PV */
+
+       es->code = calleecode;
+       es->pc = calleecode->entrypoint; /* XXX not needed? */
+       es->pv = calleecode->entrypoint;
+
+       /* write slots used for synchronization */
+
+       sp = (stackslot_t *) es->sp;
+       count = code_get_sync_slot_count(calleecode);
+       assert(count == calleeframe->syncslotcount);
+       for (i=0; i<count; ++i) {
+               sp[calleecode->memuse + i] = calleeframe->syncslots[i].p;
+       }
+
+       /* redirect future invocations */
+
+       if (callerframe && rpcall) {
+#if defined(REPLACE_PATCH_ALL)
+               if (rpcall->type == callerframe->fromrp->type)
+#else
+               if (rpcall == callerframe->fromrp)
+#endif
+                       replace_patch_future_calls(ra, callerframe, calleeframe);
+       }
+}
+
+
+/* replace_find_replacement_point **********************************************
+
+   Find the replacement point in the given code corresponding to the
+   position given in the source frame.
+   
+   IN:
+          code.............the codeinfo in which to search the rplpoint
+          frame............the source frame defining the position to look for
+          parent...........parent replacement point to match
+
+   RETURN VALUE:
+       the replacement point
+  
+*******************************************************************************/
+
+rplpoint * replace_find_replacement_point(codeinfo *code,
+                                                                                 sourceframe_t *frame,
+                                                                                 rplpoint *parent)
+{
+       methodinfo *m;
+       rplpoint *rp;
+       s4        i;
+       s4        j;
+       s4        stacki;
+       rplalloc *ra;
+
+       assert(code);
+       assert(frame);
+
+       DOLOG( printf("searching replacement point for:\n");
+                  replace_source_frame_println(frame); );
+
+       m = frame->method;
+
+       DOLOG( printf("code = %p\n", (void*)code); );
+
+       rp = code->rplpoints;
+       i = code->rplpointcount;
+       while (i--) {
+               if (rp->id == frame->id && rp->method == frame->method
+                               && rp->parent == parent
+                               && replace_normalize_type_map[rp->type] == frame->type)
+               {
+                       /* check if returnAddresses match */
+                       /* XXX optimize: only do this if JSRs in method */
+                       DOLOG( printf("checking match for:");
+                                  replace_replacement_point_println(rp, 1); fflush(stdout); );
+                       ra = rp->regalloc;
+                       stacki = 0;
+                       for (j = rp->regalloccount; j--; ++ra) {
+                               if (ra->type == TYPE_RET) {
+                                       if (ra->index == RPLALLOC_STACK) {
+                                               assert(stacki < frame->javastackdepth);
+                                               if (frame->javastack[stacki].i != ra->regoff)
+                                                       goto no_match;
+                                               stacki++;
+                                       }
+                                       else {
+                                               assert(ra->index >= 0 && ra->index < frame->javalocalcount);
+                                               if (frame->javalocals[ra->index].i != ra->regoff)
+                                                       goto no_match;
+                                       }
+                               }
+                       }
+
+                       /* found */
+                       return rp;
+               }
+no_match:
+               rp++;
+       }
+
+#if !defined(NDEBUG)
+       printf("candidate replacement points were:\n");
+       rp = code->rplpoints;
+       i = code->rplpointcount;
+       for (; i--; ++rp) {
+               replace_replacement_point_println(rp, 1);
+       }
+#endif
+
+       vm_abort("no matching replacement point found");
+       return NULL; /* NOT REACHED */
+}
+
+
+/* replace_find_replacement_point_for_pc ***************************************
+
+   Find the nearest replacement point at or before the given PC. The
+   given PC has to be between (rp->pc) and (rp->pc+rp->callsize) for
+   the replacement point to be found.
+
+   IN:
+       code.............compilation unit the PC is in
+          pc...............the machine code PC
+
+   RETURN VALUE:
+       the replacement point found, or
+          NULL if no replacement point was found
+
+*******************************************************************************/
+
+rplpoint *replace_find_replacement_point_for_pc(codeinfo *code, u1 *pc, unsigned desired_flags)
+{
+       rplpoint *found;
+       rplpoint *rp;
+       s4        i;
+
+       DOLOG( printf("searching for rp at pc:%p in %p ", (void*)pc, (void*)code);
+                  method_println(code->m); );
+
+       found = NULL;
+
+       rp = code->rplpoints;
+       for (i=0; i<code->rplpointcount; ++i, ++rp) {
+               DOLOG( replace_replacement_point_println(rp, 2); );
+               if (rp->pc <= pc && rp->pc + rp->callsize >= pc) {
+                       if (desired_flags) {
+                               if (rp->flags & desired_flags) {
+                                       found = rp;
+                               }
+                       } else {
+                               found = rp;
+                       }
+               }
+       }
+
+       return found;
+}
+
+/* replace_pop_native_frame ****************************************************
+
+   Unroll a native frame in the execution state and create a source frame
+   for it.
+
+   IN:
+          es...............current execution state
+          ss...............the current source state
+          sfi..............stackframeinfo for the native frame
+
+   OUT:
+       es...............execution state after unrolling the native frame
+          ss...............gets the added native source frame
+
+*******************************************************************************/
+
+static void replace_pop_native_frame(executionstate_t *es,
+                                                                        sourcestate_t *ss,
+                                                                        stackframeinfo_t *sfi)
+{
+       sourceframe_t *frame;
+       codeinfo      *code;
+       s4             i,j;
+
+       assert(sfi);
+
+       frame = replace_new_sourceframe(ss);
+
+       frame->sfi = sfi;
+
+       /* remember pc and size of native frame */
+
+       frame->nativepc = es->pc;
+       frame->nativeframesize = (es->sp != 0) ? (((uintptr_t) sfi->sp) - ((uintptr_t) es->sp)) : 0;
+       assert(frame->nativeframesize >= 0);
+
+       /* remember values of saved registers */
+
+       j = 0;
+       for (i=0; i<INT_REG_CNT; ++i) {
+               if (nregdescint[i] == REG_SAV)
+                       frame->nativesavint[j++] = es->intregs[i];
+       }
+
+       j = 0;
+       for (i=0; i<FLT_REG_CNT; ++i) {
+               if (nregdescfloat[i] == REG_SAV)
+                       frame->nativesavflt[j++] = es->fltregs[i];
+       }
+
+#if defined(HAS_ADDRESS_REGISTER_FILE)
+       j = 0;
+       for (i=0; i<ADR_REG_CNT; ++i) {
+               if (nregdescadr[i] == REG_SAV)
+                       frame->nativesavadr[j++] = es->adrregs[i];
+       }
+#endif
+
+       /* restore saved registers */
+
+#if defined(ENABLE_GC_CACAO) && !defined(HAS_ADDRESS_REGISTER_FILE)
+       j = 0;
+       for (i=0; i<INT_REG_CNT; ++i) {
+               if (nregdescint[i] == REG_SAV)
+                       es->intregs[i] = sfi->intregs[j++];
+       }
+#else
+       /* XXX we don't have them, yet, in the sfi, so clear them */
+
+       for (i=0; i<INT_REG_CNT; ++i) {
+               if (nregdescint[i] == REG_SAV)
+                       es->intregs[i] = 0;
+       }
+#endif
+
+       /* XXX we don't have float registers in the sfi, so clear them */
+
+       for (i=0; i<FLT_REG_CNT; ++i) {
+               if (nregdescfloat[i] == REG_SAV)
+                       es->fltregs[i] = 0.0;
+       }
+
+#if defined(HAS_ADDRESS_REGISTER_FILE)
+# if defined(ENABLE_GC_CACAO)
+       j = 0;
+       for (i=0; i<ADR_REG_CNT; ++i) {
+               if (nregdescadr[i] == REG_SAV)
+                       es->adrregs[i] = sfi->adrregs[j++];
+       }
+# else
+       for (i=0; i<ADR_REG_CNT; ++i) {
+               if (nregdescadr[i] == REG_SAV)
+                       es->adrregs[i] = 0;
+       }
+# endif
+#endif
+
+       /* restore codeinfo of the native stub */
+
+       code = code_get_codeinfo_for_pv(sfi->pv);
+
+       /* restore sp, pv, pc and codeinfo of the parent method */
+
+       /* XXX michi: use this instead:
+       es->sp = sfi->sp + code->stackframesize; */
+       es->sp   = (uint8_t*) (((uintptr_t) sfi->sp) + (*(s4 *) (((uintptr_t) sfi->pv) + FrameSize)));
+#if defined(REPLACE_RA_BETWEEN_FRAMES)
+       es->sp  += SIZE_OF_STACKSLOT; /* skip return address */
+#endif
+       es->pv   = (uint8_t*) md_codegen_get_pv_from_pc(sfi->ra);
+       es->pc   = (uint8_t*) (((uintptr_t) ((sfi->xpc) ? sfi->xpc : sfi->ra)) - 1);
+       es->code = code_get_codeinfo_for_pv(es->pv);
+}
+
+
+/* replace_push_native_frame ***************************************************
+
+   Rebuild a native frame onto the execution state and remove its source frame.
+
+   Note: The native frame is "rebuild" by setting fields like PC and stack
+         pointer in the execution state accordingly. Values in the
+                stackframeinfo may be modified, but the actual stack frame of the
+                native code is not touched.
+
+   IN:
+          es...............current execution state
+          ss...............the current source state
+
+   OUT:
+       es...............execution state after re-rolling the native frame
+          ss...............the native source frame is removed
+
+*******************************************************************************/
+
+static void replace_push_native_frame(executionstate_t *es, sourcestate_t *ss)
+{
+       sourceframe_t *frame;
+       s4             i,j;
+
+       assert(es);
+       assert(ss);
+
+       DOLOG( printf("pushing native frame\n"); );
+
+       /* remove the frame from the source state */
+
+       frame = ss->frames;
+       assert(frame);
+       assert(REPLACE_IS_NATIVE_FRAME(frame));
+
+       ss->frames = frame->down;
+
+       /* skip sp for the native stub */
+
+       es->sp -= (*(s4 *) (((uintptr_t) frame->sfi->pv) + FrameSize));
+#if defined(REPLACE_RA_BETWEEN_FRAMES)
+       es->sp -= SIZE_OF_STACKSLOT; /* skip return address */
+#endif
+
+       /* assert that the native frame has not moved */
+
+       assert(es->sp == frame->sfi->sp);
+
+       /* update saved registers in the stackframeinfo */
+
+#if defined(ENABLE_GC_CACAO)
+       j = 0;
+# if !defined(HAS_ADDRESS_REGISTER_FILE)
+       for (i=0; i<INT_REG_CNT; ++i) {
+               if (nregdescint[i] == REG_SAV)
+                       frame->sfi->intregs[j++] = es->intregs[i];
+       }
+# else
+       for (i=0; i<ADR_REG_CNT; ++i) {
+               if (nregdescadr[i] == REG_SAV)
+                       frame->sfi->adrregs[j++] = es->adrregs[i];
+       }
+# endif
+
+       /* XXX leave float registers untouched here */
+#endif
+
+       /* restore saved registers */
+
+       j = 0;
+       for (i=0; i<INT_REG_CNT; ++i) {
+               if (nregdescint[i] == REG_SAV)
+                       es->intregs[i] = frame->nativesavint[j++];
+       }
+
+       j = 0;
+       for (i=0; i<FLT_REG_CNT; ++i) {
+               if (nregdescfloat[i] == REG_SAV)
+                       es->fltregs[i] = frame->nativesavflt[j++];
+       }
+
+#if defined(HAS_ADDRESS_REGISTER_FILE)
+       j = 0;
+       for (i=0; i<ADR_REG_CNT; ++i) {
+               if (nregdescadr[i] == REG_SAV)
+                       es->adrregs[i] = frame->nativesavadr[j++];
+       }
+#endif
+
+       /* skip the native frame on the machine stack */
+
+       es->sp -= frame->nativeframesize;
+
+       /* set the pc the next frame must return to */
+
+       es->pc = frame->nativepc;
+}
+
+
+/* replace_recover_source_state ************************************************
+
+   Recover the source state from the given replacement point and execution
+   state.
+
+   IN:
+       rp...............replacement point that has been reached, if any
+          sfi..............stackframeinfo, if called from native code
+          es...............execution state at the replacement point rp
+
+   RETURN VALUE:
+       the source state
+
+*******************************************************************************/
+
+sourcestate_t *replace_recover_source_state(rplpoint *rp,
+                                                                                       stackframeinfo_t *sfi,
+                                                                                   executionstate_t *es)
+{
+       sourcestate_t *ss;
+       u1            *ra;
+       bool           locked;
+#if defined(REPLACE_STATISTICS)
+       s4             depth;
+#endif
+
+       /* create the source frame structure in dump memory */
+
+       ss = (sourcestate_t*) DumpMemory::allocate(sizeof(sourcestate_t));
+       ss->frames = NULL;
+
+       /* each iteration of the loop recovers one source frame */
+
+       depth = 0;
+       locked = false;
+
+       while (rp || sfi) {
+
+               DOLOG( executionstate_println(es); );
+
+               /* if we are not at a replacement point, it is a native frame */
+
+               if (rp == NULL) {
+                       DOLOG( printf("native frame: sfi: "); replace_stackframeinfo_println(sfi); );
+
+                       locked = true;
+                       replace_pop_native_frame(es, ss, sfi);
+                       sfi = sfi->prev;
+
+                       if (es->code == NULL)
+                               continue;
+
+                       goto after_machine_frame;
+               }
+
+               /* read the values for this source frame from the execution state */
+
+               DOLOG( printf("recovering source state for%s:\n",
+                                       (ss->frames == NULL) ? " TOPFRAME" : "");
+                          replace_replacement_point_println(rp, 1); );
+
+               replace_read_executionstate(rp, es, ss, ss->frames == NULL);
+
+#if defined(ENABLE_VMLOG)
+               vmlog_cacao_unrol_method(ss->frames->method);
+#endif
+
+#if defined(REPLACE_STATISTICS)
+               REPLACE_COUNT(stat_frames);
+               depth++;
+               replace_statistics_source_frame(ss->frames);
+#endif
+
+               /* in locked areas (below native frames), identity map the frame */
+
+               if (locked) {
+                       ss->frames->torp = ss->frames->fromrp;
+                       ss->frames->tocode = ss->frames->fromcode;
+               }
+
+               /* unroll to the next (outer) frame */
+
+               if (rp->parent) {
+                       /* this frame is in inlined code */
+
+                       DOLOG( printf("INLINED!\n"); );
+
+                       rp = rp->parent;
+
+                       assert(rp->type == RPLPOINT_TYPE_INLINE);
+                       REPLACE_COUNT(stat_unroll_inline);
+               }
+               else {
+                       /* this frame had been called at machine-level. pop it. */
+
+                       DOLOG( printf("UNWIND\n"); );
+
+                       ra = replace_pop_activation_record(es, ss->frames);
+                       if (ra == NULL) {
+                               DOLOG( printf("REACHED NATIVE CODE\n"); );
+
+                               rp = NULL;
+
+#if !defined(ENABLE_GC_CACAO)
+                               break; /* XXX remove to activate native frames */
+#endif
+                               continue;
+                       }
+
+                       /* find the replacement point at the call site */
+
+after_machine_frame:
+                       rp = replace_find_replacement_point_for_pc(es->code, es->pc, 0);
+
+                       if (rp == NULL)
+                               vm_abort("could not find replacement point while unrolling call");
+
+                       DOLOG( printf("found replacement point.\n");
+                                       replace_replacement_point_println(rp, 1); );
+
+                       assert(rp->type == RPLPOINT_TYPE_CALL);
+                       REPLACE_COUNT(stat_unroll_call);
+               }
+       } /* end loop over source frames */
+
+       REPLACE_COUNT_DIST(stat_dist_frames, depth);
+
+       return ss;
+}
+
+
+/* replace_map_source_state ****************************************************
+
+   Map each source frame in the given source state to a target replacement
+   point and compilation unit. If no valid code is available for a source
+   frame, it is (re)compiled.
+
+   IN:
+       ss...............the source state
+
+   OUT:
+       ss...............the source state, modified: The `torp` and `tocode`
+                           fields of each source frame are set.
+
+   RETURN VALUE:
+       true.............everything went ok
+          false............an exception has been thrown
+
+*******************************************************************************/
+
+static bool replace_map_source_state(sourcestate_t *ss)
+{
+       sourceframe_t *frame;
+       codeinfo      *code;
+       rplpoint      *rp;
+       rplpoint      *parent; /* parent of inlined rplpoint */
+#if defined(REPLACE_STATISTICS)
+       codeinfo      *oldcode;
+#endif
+
+       parent = NULL;
+       code = NULL;
+
+       /* iterate over the source frames from outermost to innermost */
+
+       for (frame = ss->frames; frame != NULL; frame = frame->down) {
+
+               /* XXX skip native frames */
+
+               if (REPLACE_IS_NATIVE_FRAME(frame)) {
+                       parent = NULL;
+                       continue;
+               }
+
+               /* map frames which are not already mapped */
+
+               if (frame->tocode) {
+                       code = frame->tocode;
+                       rp = frame->torp;
+                       assert(rp);
+               }
+               else {
+                       assert(frame->torp == NULL);
+
+                       if (parent == NULL) {
+                               /* find code for this frame */
+
+#if defined(REPLACE_STATISTICS)
+                               oldcode = frame->method->code;
+#endif
+                               /* request optimization of hot methods and their callers */
+
+                               if (frame->method->hitcountdown < 0
+                                       || (frame->down && frame->down->method->hitcountdown < 0))
+                                       jit_request_optimization(frame->method);
+
+                               code = jit_get_current_code(frame->method);
+
+                               if (code == NULL)
+                                       return false; /* exception */
+
+                               REPLACE_COUNT_IF(stat_recompile, code != oldcode);
+                       }
+
+                       assert(code);
+
+                       /* map this frame */
+
+                       rp = replace_find_replacement_point(code, frame, parent);
+
+                       frame->tocode = code;
+                       frame->torp = rp;
+               }
+
+               if (rp->type == RPLPOINT_TYPE_CALL) {
+                       parent = NULL;
+               }
+               else {
+                       /* inlining */
+                       parent = rp;
+               }
+       }
+
+       return true;
+}
+
+
+/* replace_map_source_state_identity *******************************************
+
+   Map each source frame in the given source state to the same replacement
+   point and compilation unit it was derived from. This is mainly used for
+   garbage collection.
+
+   IN:
+       ss...............the source state
+
+   OUT:
+       ss...............the source state, modified: The `torp` and `tocode`
+                           fields of each source frame are set.
+
+*******************************************************************************/
+
+#if defined(ENABLE_GC_CACAO)
+static void replace_map_source_state_identity(sourcestate_t *ss)
+{
+       sourceframe_t *frame;
+
+       /* iterate over the source frames from outermost to innermost */
+
+       for (frame = ss->frames; frame != NULL; frame = frame->down) {
+
+               /* skip native frames */
+
+               if (REPLACE_IS_NATIVE_FRAME(frame)) {
+                       continue;
+               }
+
+               /* map frames using the identity mapping */
+
+               if (frame->tocode) {
+                       assert(frame->tocode == frame->fromcode);
+                       assert(frame->torp   == frame->fromrp);
+               } else {
+                       assert(frame->tocode == NULL);
+                       assert(frame->torp   == NULL);
+                       frame->tocode = frame->fromcode;
+                       frame->torp   = frame->fromrp;
+               }
+       }
+}
+#endif
+
+
+/* replace_build_execution_state ***********************************************
+
+   Build an execution state for the given (mapped) source state.
+
+   !!! CAUTION: This function rewrites the machine stack !!!
+
+   THIS FUNCTION MUST BE CALLED USING A SAFE STACK AREA!
+
+   IN:
+       ss...............the source state. Must have been mapped by
+                                               replace_map_source_state before.
+          es...............the base execution state on which to build
+
+   OUT:
+       *es..............the new execution state
+
+*******************************************************************************/
+
+static void replace_build_execution_state(sourcestate_t *ss,
+                                                                                 executionstate_t *es)
+{
+       rplpoint      *rp;
+       sourceframe_t *prevframe;
+       rplpoint      *parent;
+
+       parent = NULL;
+       prevframe = NULL;
+       rp = NULL;
+
+       while (ss->frames) {
+
+               if (REPLACE_IS_NATIVE_FRAME(ss->frames)) {
+                       prevframe = ss->frames;
+                       replace_push_native_frame(es, ss);
+                       parent = NULL;
+                       rp = NULL;
+                       continue;
+               }
+
+               if (parent == NULL) {
+                       /* create a machine-level stack frame */
+
+                       DOLOG( printf("pushing activation record for:\n");
+                                  if (rp) replace_replacement_point_println(rp, 1);
+                                  else printf("\tfirst frame\n"); );
+
+                       replace_push_activation_record(es, rp, prevframe, ss->frames);
+
+                       DOLOG( executionstate_println(es); );
+               }
+
+               rp = ss->frames->torp;
+               assert(rp);
+
+               DOLOG( printf("creating execution state for%s:\n",
+                               (ss->frames->down == NULL) ? " TOPFRAME" : "");
+                          replace_replacement_point_println(ss->frames->fromrp, 1);
+                          replace_replacement_point_println(rp, 1); );
+
+               es->code = ss->frames->tocode;
+               prevframe = ss->frames;
+
+#if defined(ENABLE_VMLOG)
+               vmlog_cacao_rerol_method(ss->frames->method);
+#endif
+
+               replace_write_executionstate(rp, es, ss, ss->frames->down == NULL);
+
+               DOLOG( executionstate_println(es); );
+
+               if (rp->type == RPLPOINT_TYPE_CALL) {
+                       parent = NULL;
+               }
+               else {
+                       /* inlining */
+                       parent = rp;
+               }
+       }
+}
+
+
+/* replace_me ******************************************************************
+   This function is called by the signal handler when a thread reaches
+   a replacement point. `replace_me` must map the execution state to the
+   target replacement point and let execution continue there.
+
+   THIS FUNCTION MUST BE CALLED USING A SAFE STACK AREA!
+
+   IN:
+       rp...............replacement point that has been reached
+       es...............execution state read by signal handler
+  
+*******************************************************************************/
+
+static void replace_me(rplpoint *rp, executionstate_t *es)
+{
+       stackframeinfo_t    *sfi;
+       sourcestate_t       *ss;
+       sourceframe_t       *frame;
+       codeinfo            *origcode;
+       rplpoint            *origrp;
+#if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
+       threadobject        *thread;
+#endif
+
+       origcode = es->code;
+       origrp   = rp;
+
+#if defined(ENABLE_TLH)
+       /*printf("Replacing in %s/%s\n", rp->method->clazz->name->text, rp->method->name->text);*/
+#endif
+
+       /*if (strcmp(rp->method->clazz->name->text, "antlr/AlternativeElement") == 0 && strcmp(rp->method->name->text, "getAutoGenType") ==0) opt_TraceReplacement = 2; else opt_TraceReplacement = 0;*/
+
+       DOLOG_SHORT( printf("REPLACING(%d %p): (id %d %p) ",
+                                stat_replacements, (void*)THREADOBJECT,
+                                rp->id, (void*)rp);
+                                method_println(es->code->m); );
+
+       DOLOG( replace_replacement_point_println(rp, 1); );
+
+       REPLACE_COUNT(stat_replacements);
+
+       // Create new dump memory area.
+       DumpMemoryArea dma;
+
+       /* Get the stackframeinfo for the current thread. */
+
+       sfi = threads_get_current_stackframeinfo();
+
+       /* recover source state */
+
+       ss = replace_recover_source_state(rp, sfi, es);
+
+#if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
+       /* if there is a collection pending, we assume the replacement point should
+          suspend this thread */
+
+       if (gc_pending) {
+
+               thread = THREADOBJECT;
+
+               DOLOG_SHORT( printf("REPLACEMENT: Suspending thread for GC now!\n"); );
+
+               /* map the sourcestate using the identity mapping */
+               replace_map_source_state_identity(ss);
+
+               /* since we enter the same method again, we turn off rps now */
+               /* XXX michi: can we really do this? what if the rp was active before
+                  we activated it for the gc? */
+               replace_deactivate_replacement_points(origcode);
+
+               /* remember executionstate and sourcestate for this thread */
+               GC_EXECUTIONSTATE = es;
+               GC_SOURCESTATE    = ss;
+
+               /* really suspend this thread now (PC = 0) */
+               threads_suspend_ack(NULL, NULL);
+
+               DOLOG_SHORT( printf("REPLACEMENT: Resuming thread after GC now!\n"); );
+
+       } else {
+#endif /*defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)*/
+
+       /* map the source state */
+
+       if (!replace_map_source_state(ss))
+               vm_abort("exception during method replacement");
+
+       DOLOG( replace_sourcestate_println(ss); );
+
+       DOLOG_SHORT( replace_sourcestate_println_short(ss); );
+
+#if !defined(NDEBUG)
+       /* avoid infinite loops by self-replacement, only if not in testing mode */
+
+       if (!opt_TestReplacement) {
+               frame = ss->frames;
+               while (frame->down)
+                       frame = frame->down;
+
+               if (frame->torp == origrp) {
+                       DOLOG_SHORT(
+                               printf("WARNING: identity replacement, turning off rps to avoid infinite loop\n");
+                       );
+                       replace_deactivate_replacement_points(origcode);
+               }
+       }
+#endif
+
+#if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
+       }
+#endif
+
+       /* build the new execution state */
+
+       replace_build_execution_state(ss, es);
+
+#if !defined(NDEBUG)
+       /* continue execution after patched machine code, if testing mode enabled */
+
+       if (opt_TestReplacement)
+               es->pc += REPLACEMENT_PATCH_SIZE;
+#endif
+}
+
+
+/* replace_me_wrapper **********************************************************
+
+   This function is called by the signal handler. It determines if there
+   is an active replacement point pending at the given PC and returns
+   accordingly.
+
+   THIS FUNCTION MUST BE CALLED USING A SAFE STACK AREA!
+
+   IN:
+       pc...............the program counter that triggered the replacement.
+       context..........the context (machine state) to which the
+                           replacement should be applied.
+
+   OUT:
+       context..........the context after replacement finished.
+
+   RETURN VALUE:
+       true.............replacement done, everything went ok
+       false............no replacement done, context unchanged
+
+*******************************************************************************/
+
+bool replace_me_wrapper(u1 *pc, void *context)
+{
+       codeinfo         *code;
+       rplpoint         *rp;
+       executionstate_t  es;
+#if defined(ENABLE_RT_TIMING)
+       struct timespec time_start, time_end;
+#endif
+
+       /* search the codeinfo for the given PC */
+
+       code = code_find_codeinfo_for_pc(pc);
+       assert(code);
+
+       /* search for a replacement point at the given PC */
+
+       rp = replace_find_replacement_point_for_pc(code, pc, (RPLPOINT_FLAG_ACTIVE | RPLPOINT_FLAG_COUNTDOWN));
+
+       /* check if the replacement point belongs to given PC and is active */
+
+       if ((rp != NULL) && (rp->pc == pc)
+           && (rp->flags & (RPLPOINT_FLAG_ACTIVE | RPLPOINT_FLAG_COUNTDOWN))) {
+
+               DOLOG( printf("valid replacement point\n"); );
+
+#if !defined(NDEBUG)
+               executionstate_sanity_check(context);
+#endif
+
+               /* set codeinfo pointer in execution state */
+
+               es.code = code;
+
+               /* read execution state from current context */
+
+               md_executionstate_read(&es, context);
+
+               DOLOG( printf("REPLACEMENT READ: ");
+                          executionstate_println(&es); );
+
+               /* do the actual replacement */
+
+#if defined(ENABLE_RT_TIMING)
+               RT_TIMING_GET_TIME(time_start);
+#endif
+
+               replace_me(rp, &es);
+
+#if defined(ENABLE_RT_TIMING)
+               RT_TIMING_GET_TIME(time_end);
+               RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_REPLACE);
+#endif
+
+               /* write execution state to current context */
+
+               md_executionstate_write(&es, context);
+
+               DOLOG( printf("REPLACEMENT WRITE: ");
+                          executionstate_println(&es); );
+
+               /* new code is entered after returning */
+
+               DOLOG( printf("JUMPING IN!\n"); fflush(stdout); );
+               return true;
+       }
+       else
+               return false;
+}
+
+
+/******************************************************************************/
+/* NOTE: Stuff specific to the exact GC is below.                             */
+/******************************************************************************/
+
+#if defined(ENABLE_GC_CACAO)
+void replace_gc_from_native(threadobject *thread, u1 *pc, u1 *sp)
+{
+       stackframeinfo_t *sfi;
+       executionstate_t *es;
+       sourcestate_t    *ss;
+
+       /* Get the stackframeinfo of this thread. */
+
+       assert(thread == THREADOBJECT);
+
+       sfi = threads_get_current_stackframeinfo();
+
+       /* create the execution state */
+       es = (executionstate_t*) DumpMemory::allocate(sizeof(executionstate_t));
+       es->pc = pc;
+       es->sp = sp;
+       es->pv = 0;      /* since we are in a native, PV is invalid! */
+       es->code = NULL; /* since we are in a native, we do not have a codeinfo */
+
+       /* we assume we are in a native (no replacement point)! */
+       ss = replace_recover_source_state(NULL, sfi, es);
+
+       /* map the sourcestate using the identity mapping */
+       replace_map_source_state_identity(ss);
+
+       /* remember executionstate and sourcestate for this thread */
+       GC_EXECUTIONSTATE = es;
+       GC_SOURCESTATE    = ss;
+}
+#endif
+
+#if defined(ENABLE_GC_CACAO)
+void replace_gc_into_native(threadobject *thread)
+{
+       executionstate_t *es;
+       sourcestate_t    *ss;
+
+       /* get the executionstate and sourcestate for the given thread */
+       es = GC_EXECUTIONSTATE;
+       ss = GC_SOURCESTATE;
+
+       /* rebuild the stack of the given thread */
+       replace_build_execution_state(ss, es);
+}
+#endif
+
+
+/******************************************************************************/
+/* NOTE: No important code below.                                             */
+/******************************************************************************/
+
+
+/* statistics *****************************************************************/
+
+#if defined(REPLACE_STATISTICS)
+static void print_freq(FILE *file,int *array,int limit)
+{
+       int i;
+       int sum = 0;
+       int cum = 0;
+       for (i=0; i<limit; ++i)
+               sum += array[i];
+       sum += array[limit];
+       for (i=0; i<limit; ++i) {
+               cum += array[i];
+               fprintf(file,"      %3d: %8d (cum %3d%%)\n",
+                               i, array[i], (sum) ? ((100*cum)/sum) : 0);
+       }
+       fprintf(file,"    >=%3d: %8d\n",limit,array[limit]);
+}
+#endif /* defined(REPLACE_STATISTICS) */
+
+
+#if defined(REPLACE_STATISTICS)
+
+#define REPLACE_PRINT_DIST(name, array)                              \
+    printf("    " name " distribution:\n");                          \
+    print_freq(stdout, (array), sizeof(array)/sizeof(int) - 1);
+
+void replace_print_statistics(void)
+{
+       printf("replacement statistics:\n");
+       printf("    # of replacements:   %d\n", stat_replacements);
+       printf("    # of frames:         %d\n", stat_frames);
+       printf("    # of recompilations: %d\n", stat_recompile);
+       printf("    patched static calls:%d\n", stat_staticpatch);
+       printf("    unrolled inlines:    %d\n", stat_unroll_inline);
+       printf("    unrolled calls:      %d\n", stat_unroll_call);
+       REPLACE_PRINT_DIST("frame depth", stat_dist_frames);
+       REPLACE_PRINT_DIST("locals per frame", stat_dist_locals);
+       REPLACE_PRINT_DIST("ADR locals per frame", stat_dist_locals_adr);
+       REPLACE_PRINT_DIST("primitive locals per frame", stat_dist_locals_prim);
+       REPLACE_PRINT_DIST("RET locals per frame", stat_dist_locals_ret);
+       REPLACE_PRINT_DIST("void locals per frame", stat_dist_locals_void);
+       REPLACE_PRINT_DIST("stack slots per frame", stat_dist_stack);
+       REPLACE_PRINT_DIST("ADR stack slots per frame", stat_dist_stack_adr);
+       REPLACE_PRINT_DIST("primitive stack slots per frame", stat_dist_stack_prim);
+       REPLACE_PRINT_DIST("RET stack slots per frame", stat_dist_stack_ret);
+       printf("\n");
+       printf("    # of methods:            %d\n", stat_methods);
+       printf("    # of replacement points: %d\n", stat_rploints);
+       printf("    # of regallocs:          %d\n", stat_regallocs);
+       printf("        per rplpoint:        %f\n", (double)stat_regallocs / stat_rploints);
+       printf("        per method:          %f\n", (double)stat_regallocs / stat_methods);
+       REPLACE_PRINT_DIST("replacement points per method", stat_dist_method_rplpoints);
+       printf("\n");
+
+}
+#endif /* defined(REPLACE_STATISTICS) */
+
+
+#if defined(REPLACE_STATISTICS)
+static void replace_statistics_source_frame(sourceframe_t *frame)
+{
+       int adr = 0;
+       int ret = 0;
+       int prim = 0;
+       int vd = 0;
+       int n = 0;
+       int i;
+
+       for (i=0; i<frame->javalocalcount; ++i) {
+               switch (frame->javalocaltype[i]) {
+                       case TYPE_ADR: adr++; break;
+                       case TYPE_RET: ret++; break;
+                       case TYPE_INT: case TYPE_LNG: case TYPE_FLT: case TYPE_DBL: prim++; break;
+                       case TYPE_VOID: vd++; break;
+                       default: assert(0);
+               }
+               n++;
+       }
+       REPLACE_COUNT_DIST(stat_dist_locals, n);
+       REPLACE_COUNT_DIST(stat_dist_locals_adr, adr);
+       REPLACE_COUNT_DIST(stat_dist_locals_void, vd);
+       REPLACE_COUNT_DIST(stat_dist_locals_ret, ret);
+       REPLACE_COUNT_DIST(stat_dist_locals_prim, prim);
+       adr = ret = prim = n = 0;
+       for (i=0; i<frame->javastackdepth; ++i) {
+               switch (frame->javastacktype[i]) {
+                       case TYPE_ADR: adr++; break;
+                       case TYPE_RET: ret++; break;
+                       case TYPE_INT: case TYPE_LNG: case TYPE_FLT: case TYPE_DBL: prim++; break;
+               }
+               n++;
+       }
+       REPLACE_COUNT_DIST(stat_dist_stack, n);
+       REPLACE_COUNT_DIST(stat_dist_stack_adr, adr);
+       REPLACE_COUNT_DIST(stat_dist_stack_ret, ret);
+       REPLACE_COUNT_DIST(stat_dist_stack_prim, prim);
+}
+#endif /* defined(REPLACE_STATISTICS) */
+
+
+/* debugging helpers **********************************************************/
+
+/* replace_replacement_point_println *******************************************
+   Print replacement point info.
+  
+   IN:
+       rp...............the replacement point to print
+  
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+
+#define TYPECHAR(t)  (((t) >= 0 && (t) <= TYPE_RET) ? show_jit_type_letters[t] : '?')
+
+static const char *replace_type_str[] = {
+       "STD",
+       "EXH",
+       "SBR",
+       "CALL",
+       "INLINE",
+       "RETURN",
+       "BODY"
+};
+
+void replace_replacement_point_println(rplpoint *rp, int depth)
+{
+       int j;
+       int index;
+
+       if (!rp) {
+               printf("(rplpoint *)NULL\n");
+               return;
+       }
+
+       for (j=0; j<depth; ++j)
+               putchar('\t');
+
+       printf("rplpoint (id %d) %p pc:%p+%d type:%s",
+                       rp->id, (void*)rp,rp->pc,rp->callsize,
+                       replace_type_str[rp->type]);
+       if (rp->flags & RPLPOINT_FLAG_NOTRAP)
+               printf(" NOTRAP");
+       if (rp->flags & RPLPOINT_FLAG_COUNTDOWN)
+               printf(" COUNTDOWN");
+       if (rp->flags & RPLPOINT_FLAG_ACTIVE)
+               printf(" ACTIVE");
+       printf(" parent:%p\n", (void*)rp->parent);
+       for (j=0; j<depth; ++j)
+               putchar('\t');
+       printf("ra:%d = [",     rp->regalloccount);
+
+       for (j=0; j<rp->regalloccount; ++j) {
+               if (j)
+                       putchar(' ');
+               index = rp->regalloc[j].index;
+               switch (index) {
+                       case RPLALLOC_STACK: printf("S"); break;
+                       case RPLALLOC_PARAM: printf("P"); break;
+                       case RPLALLOC_SYNC : printf("Y"); break;
+                       default: printf("%d", index);
+               }
+               printf(":%1c:", TYPECHAR(rp->regalloc[j].type));
+               if (rp->regalloc[j].type == TYPE_RET) {
+                       printf("ret(L%03d)", rp->regalloc[j].regoff);
+               }
+               else {
+                       show_allocation(rp->regalloc[j].type, rp->regalloc[j].flags, rp->regalloc[j].regoff);
+               }
+       }
+
+       printf("]\n");
+       for (j=0; j<depth; ++j)
+               putchar('\t');
+       printf("method: ");
+       method_print(rp->method);
+
+       printf("\n");
+}
+#endif /* !defined(NDEBUG) */
+
+
+/* replace_show_replacement_points *********************************************
+   Print replacement point info.
+  
+   IN:
+       code.............codeinfo whose replacement points should be printed.
+  
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void replace_show_replacement_points(codeinfo *code)
+{
+       int i;
+       int depth;
+       rplpoint *rp;
+       rplpoint *parent;
+
+       if (!code) {
+               printf("(codeinfo *)NULL\n");
+               return;
+       }
+
+       printf("\treplacement points: %d\n",code->rplpointcount);
+
+       printf("\ttotal allocations : %d\n",code->regalloccount);
+       printf("\tsaved int regs    : %d\n",code->savedintcount);
+       printf("\tsaved flt regs    : %d\n",code->savedfltcount);
+#if defined(HAS_ADDRESS_REGISTER_FILE)
+       printf("\tsaved adr regs    : %d\n",code->savedadrcount);
+#endif
+       printf("\tmemuse            : %d\n",code->memuse);
+
+       printf("\n");
+
+       for (i=0; i<code->rplpointcount; ++i) {
+               rp = code->rplpoints + i;
+
+               depth = 1;
+               parent = rp->parent;
+               while (parent) {
+                       depth++;
+                       parent = parent->parent;
+               }
+               replace_replacement_point_println(rp, depth);
+       }
+}
+#endif
+
+
+#if !defined(NDEBUG)
+static void java_value_print(s4 type, replace_val_t value)
+{
+       java_object_t *obj;
+       utf           *u;
+
+       printf("%016llx",(unsigned long long) value.l);
+
+       if (type < 0 || type > TYPE_RET)
+               printf(" <INVALID TYPE:%d>", type);
+       else
+               printf(" %s", show_jit_type_names[type]);
+
+       if (type == TYPE_ADR && value.a != NULL) {
+               obj = value.a;
+               putchar(' ');
+               utf_display_printable_ascii_classname(obj->vftbl->clazz->name);
+
+               if (obj->vftbl->clazz == class_java_lang_String) {
+                       printf(" \"");
+                       u = javastring_toutf(obj, false);
+                       utf_display_printable_ascii(u);
+                       printf("\"");
+               }
+       }
+       else if (type == TYPE_INT) {
+               printf(" %ld", (long) value.i);
+       }
+       else if (type == TYPE_LNG) {
+               printf(" %lld", (long long) value.l);
+       }
+       else if (type == TYPE_FLT) {
+               printf(" %f", value.f);
+       }
+       else if (type == TYPE_DBL) {
+               printf(" %f", value.d);
+       }
+}
+#endif /* !defined(NDEBUG) */
+
+
+#if !defined(NDEBUG)
+void replace_source_frame_println(sourceframe_t *frame)
+{
+       s4 i,j;
+       s4 t;
+
+       if (REPLACE_IS_NATIVE_FRAME(frame)) {
+               printf("\tNATIVE\n");
+               printf("\tsfi: "); replace_stackframeinfo_println(frame->sfi);
+               printf("\tnativepc: %p\n", frame->nativepc);
+               printf("\tframesize: %d\n", frame->nativeframesize);
+
+               j = 0;
+               for (i=0; i<INT_REG_CNT; ++i) {
+                       if (nregdescint[i] == REG_SAV)
+                               printf("\t%s = %p\n", abi_registers_integer_name[i], (void*)frame->nativesavint[j++]);
+               }
+
+               j = 0;
+               for (i=0; i<FLT_REG_CNT; ++i) {
+                       if (nregdescfloat[i] == REG_SAV)
+                               printf("\tF%02d = %f\n", i, frame->nativesavflt[j++]);
+               }
+
+               printf("\n");
+               return;
+       }
+
+       printf("\t");
+       method_println(frame->method);
+       printf("\tid: %d\n", frame->id);
+       printf("\ttype: %s\n", replace_type_str[frame->type]);
+       printf("\n");
+
+       if (frame->instance.a) {
+               printf("\tinstance: ");
+               java_value_print(TYPE_ADR, frame->instance);
+               printf("\n");
+       }
+
+       if (frame->javalocalcount) {
+               printf("\tlocals (%d):\n",frame->javalocalcount);
+               for (i=0; i<frame->javalocalcount; ++i) {
+                       t = frame->javalocaltype[i];
+                       if (t == TYPE_VOID) {
+                               printf("\tlocal[ %2d] = void\n",i);
+                       }
+                       else {
+                               printf("\tlocal[%c%2d] = ",TYPECHAR(t),i);
+                               java_value_print(t, frame->javalocals[i]);
+                               printf("\n");
+                       }
+               }
+               printf("\n");
+       }
+
+       if (frame->javastackdepth) {
+               printf("\tstack (depth %d):\n",frame->javastackdepth);
+               for (i=0; i<frame->javastackdepth; ++i) {
+                       t = frame->javastacktype[i];
+                       if (t == TYPE_VOID) {
+                               printf("\tstack[%2d] = void", i);
+                       }
+                       else {
+                               printf("\tstack[%2d] = ",i);
+                               java_value_print(frame->javastacktype[i], frame->javastack[i]);
+                               printf("\n");
+                       }
+               }
+               printf("\n");
+       }
+
+       if (frame->syncslotcount) {
+               printf("\tsynchronization slots (%d):\n",frame->syncslotcount);
+               for (i=0; i<frame->syncslotcount; ++i) {
+                       printf("\tslot[%2d] = %016llx\n",i,(unsigned long long) frame->syncslots[i].p);
+               }
+               printf("\n");
+       }
+
+       if (frame->fromcode) {
+               printf("\tfrom %p ", (void*)frame->fromcode);
+               method_println(frame->fromcode->m);
+       }
+       if (frame->tocode) {
+               printf("\tto %p ", (void*)frame->tocode);
+               method_println(frame->tocode->m);
+       }
+
+       if (frame->fromrp) {
+               printf("\tfrom replacement point:\n");
+               replace_replacement_point_println(frame->fromrp, 2);
+       }
+       if (frame->torp) {
+               printf("\tto replacement point:\n");
+               replace_replacement_point_println(frame->torp, 2);
+       }
+
+       printf("\n");
+}
+#endif /* !defined(NDEBUG) */
+
+
+/* replace_sourcestate_println *************************************************
+   Print source state
+  
+   IN:
+       ss...............the source state to print
+  
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void replace_sourcestate_println(sourcestate_t *ss)
+{
+       int i;
+       sourceframe_t *frame;
+
+       if (!ss) {
+               printf("(sourcestate_t *)NULL\n");
+               return;
+       }
+
+       printf("sourcestate_t:\n");
+
+       for (i=0, frame = ss->frames; frame != NULL; frame = frame->down, ++i) {
+               printf("    frame %d:\n", i);
+               replace_source_frame_println(frame);
+       }
+}
+#endif
+
+
+/* replace_sourcestate_println_short *******************************************
+
+   Print a compact representation of the given source state.
+
+   IN:
+       ss...............the source state to print
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void replace_sourcestate_println_short(sourcestate_t *ss)
+{
+       sourceframe_t *frame;
+
+       for (frame = ss->frames; frame != NULL; frame = frame->down) {
+               printf("\t");
+
+               if (REPLACE_IS_NATIVE_FRAME(frame)) {
+                       printf("NATIVE (pc %p size %d) ",
+                                  (void*)frame->nativepc, frame->nativeframesize);
+                       replace_stackframeinfo_println(frame->sfi);
+                       continue;
+               }
+
+               if (frame->torp) {
+                       printf("%c", (frame->torp == frame->fromrp) ? '=' : '+');
+               }
+
+               printf("%s", replace_type_str[frame->fromrp->type]);
+
+               if (frame->torp && frame->torp->type != frame->fromrp->type)
+                       printf("->%s", replace_type_str[frame->torp->type]);
+
+               if (frame->tocode != frame->fromcode)
+                       printf(" (%p->%p/%d) ",
+                                  (void*) frame->fromcode, (void*) frame->tocode,
+                                  frame->fromrp->id);
+               else
+                       printf(" (%p/%d) ", (void*) frame->fromcode, frame->fromrp->id);
+
+               method_println(frame->method);
+       }
+}
+#endif
+
+#if !defined(NDEBUG)
+static void replace_stackframeinfo_println(stackframeinfo_t *sfi)
+{
+       printf("prev=%p pv=%p sp=%p ra=%p xpc=%p method=",
+                       (void*)sfi->prev, (void*)sfi->pv, (void*)sfi->sp,
+                       (void*)sfi->ra, (void*)sfi->xpc);
+
+       if (sfi->code)
+               method_println(sfi->code->m);
+       else
+               printf("(nil)\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:
+ */
diff --git a/src/vm/jit/replace.h b/src/vm/jit/replace.h
deleted file mode 100644 (file)
index 76cf081..0000000
+++ /dev/null
@@ -1,281 +0,0 @@
-/* src/vm/jit/replace.h - on-stack replacement of 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 _REPLACE_H
-#define _REPLACE_H
-
-#include "config.h"
-#include "vm/types.h"
-
-#if !defined(ENABLE_REPLACEMENT)
-
-/*** macros for the codegens (disabled version) ************************/
-
-#define REPLACEMENT_POINTS_INIT(cd, jd)
-#define REPLACEMENT_POINTS_RESET(cd, jd)
-#define REPLACEMENT_POINT_BLOCK_START(cd, bptr)
-#define REPLACEMENT_POINT_INLINE_START(cd, iptr)
-#define REPLACEMENT_POINT_INLINE_BODY(cd, iptr)
-#define REPLACEMENT_POINT_RETURN(cd, iptr)
-#define REPLACEMENT_POINT_INVOKE(cd, iptr)
-#define REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr)
-#define REPLACEMENT_POINT_FORGC_BUILTIN(cd, iptr)
-#define REPLACEMENT_POINT_FORGC_BUILTIN_RETURN(cd, iptr)
-
-#else /* defined(ENABLE_REPLACEMENT) */
-
-/* forward typedefs ***********************************************************/
-
-typedef struct rplalloc rplalloc;
-typedef struct rplpoint rplpoint;
-typedef struct sourcestate_t sourcestate_t;
-typedef struct sourceframe_t sourceframe_t;
-typedef union  replace_val_t replace_val_t;
-
-#include "arch.h"
-#include "md-abi.h"
-
-#include "vm/method.h"
-
-#include "vm/jit/reg.h"
-#include "vm/jit/stacktrace.hpp"
-
-
-/*** structs *********************************************************/
-
-#define RPLALLOC_STACK  -1
-#define RPLALLOC_PARAM  -2
-#define RPLALLOC_SYNC   -3
-
-/* `rplalloc` is a compact struct for register allocation info        */
-
-/* XXX optimize this for space efficiency */
-struct rplalloc {
-       s4           index;     /* local index, -1 for stack slot         */
-       s4           regoff;    /* register index / stack slot offset     */
-       unsigned int flags:4;   /* OR of (INMEMORY,...)                   */
-       unsigned int type:4;    /* TYPE_... constant                      */
-};
-
-#if INMEMORY > 0x08
-#error value of INMEMORY is too big to fit in rplalloc.flags
-#endif
-
-
-/* XXX what to do about overlapping rplpoints? */
-/* CAUTION: Do not change the numerical values. These are used as     */
-/*          indices into replace_normalize_type_map.                  */
-#define RPLPOINT_TYPE_STD     BBTYPE_STD
-#define RPLPOINT_TYPE_EXH     BBTYPE_EXH
-#define RPLPOINT_TYPE_SBR     BBTYPE_SBR
-#define RPLPOINT_TYPE_CALL    3
-#define RPLPOINT_TYPE_INLINE  4
-#define RPLPOINT_TYPE_RETURN  5
-#define RPLPOINT_TYPE_BODY    6
-
-#define RPLPOINT_FLAG_NOTRAP     0x01  /* rplpoint cannot be trapped */
-#define RPLPOINT_FLAG_COUNTDOWN  0x02  /* count down hits            */
-#define RPLPOINT_FLAG_ACTIVE     0x08  /* trap is active             */
-
-
-#if !defined(NDEBUG)
-#define RPLPOINT_CHECK(type)     , RPLPOINT_TYPE_##type
-#define RPLPOINT_CHECK_BB(bptr)  , (bptr)->type
-#else
-#define RPLPOINT_CHECK(type)
-#define RPLPOINT_CHECK_BB(bptr)
-#endif
-
-
-/* An `rplpoint` represents a replacement point in a compiled method  */
-
-struct rplpoint {
-       u1          *pc;           /* machine code PC of this point       */
-       methodinfo  *method;       /* source method this point is in      */
-       rplpoint    *parent;       /* rplpoint of the inlined body        */ /* XXX unify with code */
-       rplalloc    *regalloc;     /* pointer to register index table     */
-       s4           id;           /* id of the rplpoint within method    */
-       s4           callsize;     /* size of call code in bytes          */
-       unsigned int regalloccount:20; /* number of local allocations     */
-       unsigned int type:4;           /* RPLPOINT_TYPE_... constant      */
-       unsigned int flags:8;          /* OR of RPLPOINT_... constants    */
-};
-
-
-union replace_val_t {
-       s4             i;
-       s8             l;
-       ptrint         p;
-       struct {
-               u4 lo;
-               u4 hi;
-       }              words;
-       float          f;
-       double         d;
-       java_object_t *a;
-};
-
-
-struct sourceframe_t {
-       sourceframe_t *down;           /* source frame down the call chain */
-
-       methodinfo    *method;                  /* method this frame is in */
-       s4             id;
-       s4             type;
-
-       /* values */
-       replace_val_t  instance;
-
-       replace_val_t *javastack;                  /* values of stack vars */
-       u1            *javastacktype;              /*  types of stack vars */
-       s4             javastackdepth;             /* number of stack vars */
-
-       replace_val_t *javalocals;                 /* values of javalocals */
-       u1            *javalocaltype;              /*  types of javalocals */
-       s4             javalocalcount;             /* number of javalocals */
-
-       replace_val_t *syncslots;
-       s4             syncslotcount; /* XXX do we need more than one? */
-
-       /* mapping info */
-       rplpoint      *fromrp;         /* rplpoint used to read this frame */
-       codeinfo      *fromcode;              /* code this frame was using */
-       rplpoint      *torp;          /* rplpoint this frame was mapped to */
-       codeinfo      *tocode;            /* code this frame was mapped to */
-
-       /* info for native frames */
-       stackframeinfo_t *sfi;      /* sfi for native frames, otherwise NULL */
-       s4             nativeframesize;    /* size (bytes) of native frame */
-       u1            *nativepc;
-       ptrint         nativesavint[INT_SAV_CNT]; /* XXX temporary */
-       double         nativesavflt[FLT_REG_CNT]; /* XXX temporary */
-#if defined(HAS_ADDRESS_REGISTER_FILE)
-       ptrint         nativesavadr[ADR_SAV_CNT]; /* XXX temporary */
-#endif
-};
-
-#define REPLACE_IS_NATIVE_FRAME(frame)  ((frame)->sfi != NULL)
-#define REPLACE_IS_JAVA_FRAME(frame)    ((frame)->sfi == NULL)
-
-
-struct sourcestate_t {
-       sourceframe_t *frames;    /* list of source frames, from bottom up */
-};
-
-
-/*** macros for the codegens *******************************************/
-
-#define REPLACEMENT_POINTS_INIT(cd, jd)                              \
-    if (!replace_create_replacement_points(jd))                      \
-        return false;                                                \
-    (cd)->replacementpoint = (jd)->code->rplpoints;
-
-#define REPLACEMENT_POINTS_RESET(cd, jd)                             \
-    (cd)->replacementpoint = (jd)->code->rplpoints;
-
-#define REPLACEMENT_POINT_BLOCK_START(cd, bptr)                      \
-    if ((bptr)->bitflags & BBFLAG_REPLACEMENT)                       \
-        codegen_set_replacement_point((cd) RPLPOINT_CHECK_BB(bptr));
-
-#define REPLACEMENT_POINT_INLINE_START(cd, iptr)                     \
-    codegen_set_replacement_point(cd RPLPOINT_CHECK(INLINE));
-
-#define REPLACEMENT_POINT_INLINE_BODY(cd, iptr)                      \
-    codegen_set_replacement_point_notrap(cd RPLPOINT_CHECK(BODY));
-
-#define REPLACEMENT_POINT_RETURN(cd, iptr)                           \
-    codegen_set_replacement_point(cd RPLPOINT_CHECK(RETURN));
-
-#define REPLACEMENT_POINT_INVOKE(cd, iptr)                           \
-    codegen_set_replacement_point(cd RPLPOINT_CHECK(CALL));
-
-#define REPLACEMENT_POINT_INVOKE_RETURN(cd,  iptr)                   \
-    if (iptr->opc != ICMD_BUILTIN)                                   \
-        cd->replacementpoint[-1].callsize = (cd->mcodeptr - cd->mcodebase)\
-                    - (ptrint) cd->replacementpoint[-1].pc;
-
-
-/*** macros for the codegens (for GC) **********************************/
-
-#if defined(ENABLE_GC_CACAO)
-
-#define REPLACEMENT_POINT_FORGC_BUILTIN(cd, iptr)                    \
-       codegen_set_replacement_point(cd RPLPOINT_CHECK(CALL));
-
-#define REPLACEMENT_POINT_FORGC_BUILTIN_RETURN(cd, iptr)             \
-       if (iptr->opc == ICMD_BUILTIN)                                   \
-               cd->replacementpoint[-1].callsize = (cd->mcodeptr - cd->mcodebase)\
-                                       - (ptrint) cd->replacementpoint[-1].pc;
-
-#else /* defined(ENABLE_GC_CACAO) */
-
-#define REPLACEMENT_POINT_FORGC_BUILTIN(cd, iptr)
-#define REPLACEMENT_POINT_FORGC_BUILTIN_RETURN(cd, iptr)
-
-#endif /* defined(ENABLE_GC_CACAO) */
-
-
-/*** prototypes ********************************************************/
-
-bool replace_create_replacement_points(jitdata *jd);
-void replace_free_replacement_points(codeinfo *code);
-
-void replace_activate_replacement_points(codeinfo *code, bool mappable);
-void replace_deactivate_replacement_points(codeinfo *code);
-
-bool replace_me_wrapper(u1 *pc, void *context);
-
-#if !defined(NDEBUG)
-void replace_show_replacement_points(codeinfo *code);
-void replace_replacement_point_println(rplpoint *rp, int depth);
-void replace_sourcestate_println(sourcestate_t *ss);
-void replace_sourcestate_println_short(sourcestate_t *ss);
-void replace_source_frame_println(sourceframe_t *frame);
-#endif
-
-/* machine dependent functions (code in ARCH_DIR/md.c) */
-
-#if defined(ENABLE_JIT)
-void md_patch_replacement_point(u1 *pc, u1 *savedmcode, bool revert);
-#endif
-
-#endif /* defined(ENABLE_REPLACEMENT) */
-
-#endif /* _REPLACE_H */
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
diff --git a/src/vm/jit/replace.hpp b/src/vm/jit/replace.hpp
new file mode 100644 (file)
index 0000000..20b61ec
--- /dev/null
@@ -0,0 +1,289 @@
+/* src/vm/jit/replace.hpp - on-stack replacement of 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 _REPLACE_HPP
+#define _REPLACE_HPP
+
+#include "config.h"
+#include "vm/types.h"
+
+#if !defined(ENABLE_REPLACEMENT)
+
+/*** macros for the codegens (disabled version) ************************/
+
+#define REPLACEMENT_POINTS_INIT(cd, jd)
+#define REPLACEMENT_POINTS_RESET(cd, jd)
+#define REPLACEMENT_POINT_BLOCK_START(cd, bptr)
+#define REPLACEMENT_POINT_INLINE_START(cd, iptr)
+#define REPLACEMENT_POINT_INLINE_BODY(cd, iptr)
+#define REPLACEMENT_POINT_RETURN(cd, iptr)
+#define REPLACEMENT_POINT_INVOKE(cd, iptr)
+#define REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr)
+#define REPLACEMENT_POINT_FORGC_BUILTIN(cd, iptr)
+#define REPLACEMENT_POINT_FORGC_BUILTIN_RETURN(cd, iptr)
+
+#else /* defined(ENABLE_REPLACEMENT) */
+
+/* forward typedefs ***********************************************************/
+
+typedef struct rplalloc rplalloc;
+typedef struct rplpoint rplpoint;
+typedef struct sourcestate_t sourcestate_t;
+typedef struct sourceframe_t sourceframe_t;
+typedef union  replace_val_t replace_val_t;
+
+#include "arch.h"
+#include "md-abi.h"
+
+#include "vm/method.h"
+
+#include "vm/jit/reg.h"
+#include "vm/jit/stacktrace.hpp"
+
+
+/*** structs *********************************************************/
+
+#define RPLALLOC_STACK  -1
+#define RPLALLOC_PARAM  -2
+#define RPLALLOC_SYNC   -3
+
+/* `rplalloc` is a compact struct for register allocation info        */
+
+/* XXX optimize this for space efficiency */
+struct rplalloc {
+       s4           index;     /* local index, -1 for stack slot         */
+       s4           regoff;    /* register index / stack slot offset     */
+       unsigned int flags:4;   /* OR of (INMEMORY,...)                   */
+       unsigned int type:4;    /* TYPE_... constant                      */
+};
+
+#if INMEMORY > 0x08
+#error value of INMEMORY is too big to fit in rplalloc.flags
+#endif
+
+
+/* XXX what to do about overlapping rplpoints? */
+/* CAUTION: Do not change the numerical values. These are used as     */
+/*          indices into replace_normalize_type_map.                  */
+#define RPLPOINT_TYPE_STD     BBTYPE_STD
+#define RPLPOINT_TYPE_EXH     BBTYPE_EXH
+#define RPLPOINT_TYPE_SBR     BBTYPE_SBR
+#define RPLPOINT_TYPE_CALL    3
+#define RPLPOINT_TYPE_INLINE  4
+#define RPLPOINT_TYPE_RETURN  5
+#define RPLPOINT_TYPE_BODY    6
+
+#define RPLPOINT_FLAG_NOTRAP     0x01  /* rplpoint cannot be trapped */
+#define RPLPOINT_FLAG_COUNTDOWN  0x02  /* count down hits            */
+#define RPLPOINT_FLAG_ACTIVE     0x08  /* trap is active             */
+
+
+#if !defined(NDEBUG)
+#define RPLPOINT_CHECK(type)     , RPLPOINT_TYPE_##type
+#define RPLPOINT_CHECK_BB(bptr)  , (bptr)->type
+#else
+#define RPLPOINT_CHECK(type)
+#define RPLPOINT_CHECK_BB(bptr)
+#endif
+
+
+/* An `rplpoint` represents a replacement point in a compiled method  */
+
+struct rplpoint {
+       u1          *pc;           /* machine code PC of this point       */
+       methodinfo  *method;       /* source method this point is in      */
+       rplpoint    *parent;       /* rplpoint of the inlined body        */ /* XXX unify with code */
+       rplalloc    *regalloc;     /* pointer to register index table     */
+       s4           id;           /* id of the rplpoint within method    */
+       s4           callsize;     /* size of call code in bytes          */
+       unsigned int regalloccount:20; /* number of local allocations     */
+       unsigned int type:4;           /* RPLPOINT_TYPE_... constant      */
+       unsigned int flags:8;          /* OR of RPLPOINT_... constants    */
+};
+
+
+union replace_val_t {
+       s4             i;
+       s8             l;
+       ptrint         p;
+       struct {
+               u4 lo;
+               u4 hi;
+       }              words;
+       float          f;
+       double         d;
+       java_object_t *a;
+};
+
+
+struct sourceframe_t {
+       sourceframe_t *down;           /* source frame down the call chain */
+
+       methodinfo    *method;                  /* method this frame is in */
+       s4             id;
+       s4             type;
+
+       /* values */
+       replace_val_t  instance;
+
+       replace_val_t *javastack;                  /* values of stack vars */
+       u1            *javastacktype;              /*  types of stack vars */
+       s4             javastackdepth;             /* number of stack vars */
+
+       replace_val_t *javalocals;                 /* values of javalocals */
+       u1            *javalocaltype;              /*  types of javalocals */
+       s4             javalocalcount;             /* number of javalocals */
+
+       replace_val_t *syncslots;
+       s4             syncslotcount; /* XXX do we need more than one? */
+
+       /* mapping info */
+       rplpoint      *fromrp;         /* rplpoint used to read this frame */
+       codeinfo      *fromcode;              /* code this frame was using */
+       rplpoint      *torp;          /* rplpoint this frame was mapped to */
+       codeinfo      *tocode;            /* code this frame was mapped to */
+
+       /* info for native frames */
+       stackframeinfo_t *sfi;      /* sfi for native frames, otherwise NULL */
+       s4             nativeframesize;    /* size (bytes) of native frame */
+       u1            *nativepc;
+       ptrint         nativesavint[INT_SAV_CNT]; /* XXX temporary */
+       double         nativesavflt[FLT_REG_CNT]; /* XXX temporary */
+#if defined(HAS_ADDRESS_REGISTER_FILE)
+       ptrint         nativesavadr[ADR_SAV_CNT]; /* XXX temporary */
+#endif
+};
+
+#define REPLACE_IS_NATIVE_FRAME(frame)  ((frame)->sfi != NULL)
+#define REPLACE_IS_JAVA_FRAME(frame)    ((frame)->sfi == NULL)
+
+
+struct sourcestate_t {
+       sourceframe_t *frames;    /* list of source frames, from bottom up */
+};
+
+
+/*** macros for the codegens *******************************************/
+
+#define REPLACEMENT_POINTS_INIT(cd, jd)                              \
+    if (!replace_create_replacement_points(jd))                      \
+        return false;                                                \
+    (cd)->replacementpoint = (jd)->code->rplpoints;
+
+#define REPLACEMENT_POINTS_RESET(cd, jd)                             \
+    (cd)->replacementpoint = (jd)->code->rplpoints;
+
+#define REPLACEMENT_POINT_BLOCK_START(cd, bptr)                      \
+    if ((bptr)->bitflags & BBFLAG_REPLACEMENT)                       \
+        codegen_set_replacement_point((cd) RPLPOINT_CHECK_BB(bptr));
+
+#define REPLACEMENT_POINT_INLINE_START(cd, iptr)                     \
+    codegen_set_replacement_point(cd RPLPOINT_CHECK(INLINE));
+
+#define REPLACEMENT_POINT_INLINE_BODY(cd, iptr)                      \
+    codegen_set_replacement_point_notrap(cd RPLPOINT_CHECK(BODY));
+
+#define REPLACEMENT_POINT_RETURN(cd, iptr)                           \
+    codegen_set_replacement_point(cd RPLPOINT_CHECK(RETURN));
+
+#define REPLACEMENT_POINT_INVOKE(cd, iptr)                           \
+    codegen_set_replacement_point(cd RPLPOINT_CHECK(CALL));
+
+#define REPLACEMENT_POINT_INVOKE_RETURN(cd,  iptr)                   \
+    if (iptr->opc != ICMD_BUILTIN)                                   \
+        cd->replacementpoint[-1].callsize = (cd->mcodeptr - cd->mcodebase)\
+                    - (ptrint) cd->replacementpoint[-1].pc;
+
+
+/*** macros for the codegens (for GC) **********************************/
+
+#if defined(ENABLE_GC_CACAO)
+
+#define REPLACEMENT_POINT_FORGC_BUILTIN(cd, iptr)                    \
+       codegen_set_replacement_point(cd RPLPOINT_CHECK(CALL));
+
+#define REPLACEMENT_POINT_FORGC_BUILTIN_RETURN(cd, iptr)             \
+       if (iptr->opc == ICMD_BUILTIN)                                   \
+               cd->replacementpoint[-1].callsize = (cd->mcodeptr - cd->mcodebase)\
+                                       - (ptrint) cd->replacementpoint[-1].pc;
+
+#else // ENABLE_GC_CACAO
+
+#define REPLACEMENT_POINT_FORGC_BUILTIN(cd, iptr)
+#define REPLACEMENT_POINT_FORGC_BUILTIN_RETURN(cd, iptr)
+
+#endif // ENABLE_GC_CACAO
+
+
+/*** prototypes ********************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool replace_create_replacement_points(jitdata *jd);
+void replace_free_replacement_points(codeinfo *code);
+
+void replace_activate_replacement_points(codeinfo *code, bool mappable);
+void replace_deactivate_replacement_points(codeinfo *code);
+
+bool replace_me_wrapper(u1 *pc, void *context);
+
+#if !defined(NDEBUG)
+void replace_show_replacement_points(codeinfo *code);
+void replace_replacement_point_println(rplpoint *rp, int depth);
+void replace_sourcestate_println(sourcestate_t *ss);
+void replace_sourcestate_println_short(sourcestate_t *ss);
+void replace_source_frame_println(sourceframe_t *frame);
+#endif
+
+/* machine dependent functions (code in ARCH_DIR/md.c) */
+
+#if defined(ENABLE_JIT)
+void md_patch_replacement_point(u1 *pc, u1 *savedmcode, bool revert);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // ENABLE_REPLACEMENT
+
+#endif // _REPLACE_HPP
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
index 7e17c12f7efcedac2527c2c647fa199653a298c6..002ce18e8c3e5ead51b342003f0c852aceb47dad 100644 (file)
@@ -51,6 +51,7 @@ libarch_la_SOURCES = \
        \
        md-abi.c \
        md-abi.h \
+       md-stubs.hpp \
        md-trap.h \
        md.c \
        md.h
index f09c7c8046b21695a5f9851bf06b48408e8fee29..002ba7f956db07116bfbffcb4dcdf4a397bb72fa 100644 (file)
@@ -33,8 +33,6 @@
 
 /* define architecture features ***********************************************/
 
-#define U8_AVAILABLE                     1
-
 #define SUPPORT_DIVISION                 1
 #define SUPPORT_LONG                     1
 
index 72e5bc3c3d47ad62791ae7d5dd91a08f0f8da244..7db818cadc79711f99fd64de3a56a1a58bc99968 100644 (file)
 #include "vm/jit/s390/emit.h"
 #include "vm/jit/s390/md-abi.h"
 
-#include "native/jni.h"
-#include "native/localref.h"
-#include "native/native.h"
+#include "native/localref.hpp"
+#include "native/native.hpp"
 
 #include "mm/memory.h"
 
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/exceptions.hpp"
 #include "vm/global.h"
-#include "vm/loader.h"
+#include "vm/loader.hpp"
 #include "vm/options.h"
 #include "vm/statistics.h"
 #include "vm/types.h"
 # include "vm/jit/allocator/lsra.h"
 #endif
 #include "vm/jit/asmpart.h"
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/codegen-common.hpp"
 #include "vm/jit/dseg.h"
-#include "vm/jit/emit-common.h"
-#include "vm/jit/jit.h"
-#include "vm/jit/linenumbertable.h"
+#include "vm/jit/emit-common.hpp"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/linenumbertable.hpp"
 #include "vm/jit/methodheader.h"
 #include "vm/jit/parse.h"
-#include "vm/jit/patcher-common.h"
+#include "vm/jit/patcher-common.hpp"
 #include "vm/jit/reg.h"
-#include "vm/jit/replace.h"
+#include "vm/jit/replace.hpp"
 #include "vm/jit/stacktrace.hpp"
 #include "vm/jit/trap.h"
 
index 8cb750ac9e50340626144c4f53efead7f62ca56f..3e5262d459631f77cad2ac7bf499570b7a9d1f61 100644 (file)
@@ -1,9 +1,7 @@
 /* src/vm/jit/s390/codegen.h - code generation macros for s390
 
-   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
-   C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
-   E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
-   J. Wenninger, Institut f. Computersprachen - TU Wien
+   Copyright (C) 1996-2005, 2006, 2007, 2008
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
 
@@ -34,7 +32,7 @@
 
 #include "vm/types.h"
 
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
 
 
 /* MCODECHECK(icnt) */
@@ -49,7 +47,6 @@
 
 #define PATCHER_CALL_SIZE    2          /* size in bytes of a patcher call    */
 #define PATCHER_NOPS M_NOP3
-#define PATCHER_NOPS_SKIP   2
 
 /* branch defines ************************************************************/
 
@@ -64,9 +61,6 @@
                } \
        } while (0) 
 
-/* stub defines **************************************************************/
-
-#define COMPILERSTUB_CODESIZE    (SZ_AHI + SZ_L + SZ_L + SZ_BCR)
 
 /* *** BIG TODO ***
  * Make all this inline functions !!!!!!!!!!
index 00467f338d486b82f1af6986c5b03f39cbd472e6..ef5c2289c0135f08b54fb810b268fa5aa0ee566a 100644 (file)
@@ -33,9 +33,9 @@
 
 #include "mm/memory.h"
 
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #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/asmpart.h"
-#include "vm/jit/codegen-common.h"
-#include "vm/jit/emit-common.h"
-#include "vm/jit/jit.h"
-#include "vm/jit/patcher-common.h"
-#include "vm/jit/replace.h"
+#include "vm/jit/codegen-common.hpp"
+#include "vm/jit/emit-common.hpp"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/patcher-common.hpp"
+#include "vm/jit/replace.hpp"
 #include "vm/jit/trace.hpp"
 #include "vm/jit/trap.h"
 
index 7f9017ca4fab272b70e198f8e2143e78eb2021ec..95ad22ac5d0e1e6be847fa5f99c2d56d075a872f 100644 (file)
@@ -29,7 +29,7 @@
 #include "vm/global.h"
 #include "vm/types.h"
 
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
 #include "vm/jit/stack.h"
 
 #include "vm/jit/s390/md-abi.h"
diff --git a/src/vm/jit/s390/md-stubs.hpp b/src/vm/jit/s390/md-stubs.hpp
new file mode 100644 (file)
index 0000000..6fbe822
--- /dev/null
@@ -0,0 +1,58 @@
+/* src/vm/jit/s390/md-stubs.hpp - s390 JIT stubs
+
+   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 _MD_STUBS_HPP
+#define _MD_STUBS_HPP
+
+#include "config.h"
+
+#include "vm/jit/s390/codegen.h"
+
+
+/**
+ * Return the code size of a compiler on a s390 architecture.
+ *
+ * @return Code size in bytes.
+ */
+int CompilerStub::get_code_size()
+{
+       return (SZ_AHI + SZ_L + SZ_L + SZ_BCR);
+}
+
+#endif // _MD_STUBS_HPP
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
index 917e17a3c93ee2ab4f7edd0e69363f2216329685..5e11280ac1dc33ceeb731e5cd3ec03929b100126 100644 (file)
@@ -52,7 +52,7 @@
 #include "vm/jit/disass.h" /* XXX debug */
 #endif
 
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/codegen-common.hpp"
 #include "vm/jit/s390/codegen.h"
 #include "vm/jit/s390/md.h"
 
index 1664cd4172cbfa4b9faa37f3394edc8f04e569ad..cbb7f9b6df26dd1609b9144d02f7a4548aa306be 100644 (file)
@@ -31,7 +31,7 @@
 #include <assert.h>
 #include <stdint.h>
 
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/codegen-common.hpp"
 #include "vm/jit/methodtree.h"
 
 
index 94e40a9ff82b2f19dde32b86d7ba44c3ab6e69cc..4fdd63ff11a6f915739bb15efe512003c035c637 100644 (file)
 #include <stdint.h>
 
 #include "mm/memory.h"
-#include "native/native.h"
+#include "native/native.hpp"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/class.h"
-#include "vm/field.h"
+#include "vm/field.hpp"
 #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/patcher-common.hpp"
 #include "vm/jit/s390/codegen.h"
 #include "vm/jit/s390/md-abi.h"
 
@@ -131,11 +131,6 @@ bool patcher_get_putfield(patchref_t *pr)
 
        PATCH_BACK_ORIGINAL_MCODE;
 
-       /* If NOPs are generated, skip them */
-
-       if (opt_shownops)
-               ra += PATCHER_NOPS_SKIP;
-
        /* If there is an operand load before, skip the load size passed in disp (see ICMD_PUTFIELD) */
 
        ra += disp;
@@ -219,11 +214,6 @@ bool patcher_invokevirtual(patchref_t *pr)
 
        PATCH_BACK_ORIGINAL_MCODE;
 
-       /* If NOPs are generated, skip them */
-
-       if (opt_shownops)
-               ra += PATCHER_NOPS_SKIP;
-
        /* patch vftbl index */
 
 
@@ -267,11 +257,6 @@ bool patcher_invokeinterface(patchref_t *pr)
 
        PATCH_BACK_ORIGINAL_MCODE;
 
-       /* If NOPs are generated, skip them */
-
-       if (opt_shownops)
-               ra += PATCHER_NOPS_SKIP;
-
        /* get interfacetable index */
 
        idx = (s4) (OFFSET(vftbl_t, interfacetable[0]) -
@@ -428,11 +413,6 @@ bool patcher_checkcast_instanceof_interface(patchref_t *pr)
 
        PATCH_BACK_ORIGINAL_MCODE;
 
-       /* If NOPs are generated, skip them */
-
-       if (opt_shownops)
-               ra += PATCHER_NOPS_SKIP;
-
        /* patch super class index */
 
        /* From here, split your editor and open codegen.c */
diff --git a/src/vm/jit/show.c b/src/vm/jit/show.c
deleted file mode 100644 (file)
index 55e3592..0000000
+++ /dev/null
@@ -1,1683 +0,0 @@
-/* src/vm/jit/show.c - showing the intermediate representation
-
-   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 "threads/lock-common.h"
-
-#include "vm/global.h"
-#include "vm/builtin.h"
-#include "vm/options.h"
-#include "vm/string.hpp"
-#include "vm/vm.hpp"
-
-#include "vm/jit/abi.h"
-#include "vm/jit/jit.h"
-#include "vm/jit/show.h"
-#include "vm/jit/disass.h"
-#include "vm/jit/stack.h"
-#include "vm/jit/parse.h"
-
-#if defined(ENABLE_DEBUG_FILTER)
-# include <sys/types.h>
-# include <regex.h>
-# include "threads/thread.hpp"
-#endif
-
-
-/* global variables ***********************************************************/
-
-#if !defined(NDEBUG)
-static Mutex* mutex;
-#endif
-
-
-/* prototypes *****************************************************************/
-
-#if !defined(NDEBUG)
-static void show_variable_intern(jitdata *jd, s4 index, int stage);
-#endif
-
-
-/* show_init *******************************************************************
-
-   Initialized the show subsystem (called by jit_init).
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-bool show_init(void)
-{
-#if defined(ENABLE_THREADS)
-       /* initialize the show lock */
-
-       mutex = Mutex_new();
-#endif
-
-#if defined(ENABLE_DEBUG_FILTER)
-       show_filters_init();
-#endif
-
-       /* everything's ok */
-
-       return true;
-}
-#endif
-
-
-#if !defined(NDEBUG)
-char *show_jit_type_names[] = {
-       "INT",
-       "LNG",
-       "FLT",
-       "DBL",
-       "ADR",
-       "??5",
-       "??6",
-       "??7",
-       "RET"
-};
-char show_jit_type_letters[] = {
-       'I',
-       'L',
-       'F',
-       'D',
-       'A',
-       '5',
-       '6',
-       '7',
-       'R'
-};
-#endif
-
-
-/* show_method *****************************************************************
-
-   Print the intermediate representation of a method.
-
-   NOTE: Currently this function may only be called after register allocation!
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-void show_method(jitdata *jd, int stage)
-{
-       methodinfo     *m;
-       codeinfo       *code;
-       codegendata    *cd;
-       registerdata   *rd;
-       basicblock     *bptr;
-       basicblock     *lastbptr;
-       exception_entry *ex;
-       s4              i, j;
-       int             irstage;
-#if defined(ENABLE_DISASSEMBLER)
-       u1             *pc;
-#endif
-
-       /* get required compiler data */
-
-       m    = jd->m;
-       code = jd->code;
-       cd   = jd->cd;
-       rd   = jd->rd;
-
-       /* We need to enter a lock here, since the binutils disassembler
-          is not reentrant-able and we could not read functions printed
-          at the same time. */
-
-       Mutex_lock(mutex);
-
-#if defined(ENABLE_INTRP)
-       if (opt_intrp)
-               irstage = SHOW_PARSE;
-       else
-#endif
-               irstage = stage;
-
-       /* get the last basic block */
-
-       for (lastbptr = jd->basicblocks; lastbptr->next != NULL; lastbptr = lastbptr->next);
-
-       printf("\n");
-
-       method_println(m);
-
-       if (code_is_leafmethod(code))
-               printf("LEAFMETHOD\n");
-
-       printf("\nBasic blocks: %d\n", jd->basicblockcount);
-       if (stage >= SHOW_CODE) {
-               printf("Code length:  %d\n", (lastbptr->mpc - jd->basicblocks[0].mpc));
-               printf("Data length:  %d\n", cd->dseglen);
-               printf("Stub length:  %d\n", (s4) (code->mcodelength -
-                                                                                  ((ptrint) cd->dseglen + lastbptr->mpc)));
-       }
-       printf("Variables:       %d (%d used)\n", jd->varcount, jd->vartop);
-       if (stage >= SHOW_STACK)
-               printf("Max interfaces:  %d\n", jd->maxinterfaces);
-       printf("Max locals:      %d\n", jd->maxlocals);
-       printf("Max stack:       %d\n", m->maxstack);
-       printf("Linenumbers:     %d\n", m->linenumbercount);
-       printf("Branch to entry: %s\n", (jd->branchtoentry) ? "yes" : "no");
-       printf("Branch to end:   %s\n", (jd->branchtoend) ? "yes" : "no");
-       if (stage >= SHOW_STACK) {
-               printf("Number of RETURNs: %d", jd->returncount);
-               if (jd->returncount == 1)
-                       printf(" (block L%03d)", jd->returnblock->nr);
-               printf("\n");
-       }
-
-       if (stage >= SHOW_PARSE) {
-               printf("Exceptions (Number: %d):\n", jd->exceptiontablelength);
-               for (ex = jd->exceptiontable; ex != NULL; ex = ex->down) {
-                       printf("    L%03d ... ", ex->start->nr );
-                       printf("L%03d  = ", ex->end->nr);
-                       printf("L%03d", ex->handler->nr);
-                       printf("  (catchtype: ");
-                       if (ex->catchtype.any)
-                               if (IS_CLASSREF(ex->catchtype))
-                                       class_classref_print(ex->catchtype.ref);
-                               else
-                                       class_print(ex->catchtype.cls);
-                       else
-                               printf("ANY");
-                       printf(")\n");
-               }
-       }
-       
-       if (irstage >= SHOW_PARSE && rd && jd->localcount > 0) {
-               printf("Local Table:\n");
-               for (i = 0; i < jd->localcount; i++) {
-                       printf("   %3d: ", i);
-
-#if defined(ENABLE_JIT) && defined(ENABLE_DISASSEMBLER)
-# if defined(ENABLE_INTRP)
-                       if (!opt_intrp) {
-# endif
-                               printf("   (%s) ", show_jit_type_names[VAR(i)->type]);
-                               if (irstage >= SHOW_REGS)
-                                       show_allocation(VAR(i)->type, VAR(i)->flags, VAR(i)->vv.regoff);
-                               printf("\n");
-# if defined(ENABLE_INTRP)
-                       }
-# endif
-#endif /* defined(ENABLE_JIT) && defined(ENABLE_DISASSEMBLER) */
-               }
-               printf("\n");
-       }
-
-       if (jd->maxlocals > 0 && jd->local_map != NULL) {
-               printf("Local Map:\n");
-               printf("    index ");
-               for (j = 0; j < jd->maxlocals; j++) {
-                       printf(" [%2d]", j);
-               }
-               printf("\n");
-               for (i = 0; i < 5; i++) {
-                       printf("    %5s ",show_jit_type_names[i]);
-                       for (j = 0; j < jd->maxlocals; j++) {
-                               if (jd->local_map[j*5+i] == UNUSED)
-                                       printf("  -- ");
-                               else
-                                       printf("%4i ",jd->local_map[j*5+i]);
-                       }
-                       printf("\n");
-               }
-               printf("\n");
-       }
-
-       if (jd->maxinterfaces > 0 && jd->interface_map && irstage >= SHOW_STACK) {
-               bool exist = false;
-               interface_info *mapptr = jd->interface_map;
-               
-               /* look if there exist any INOUTS */
-               for (i = 0; (i < (5 * jd->maxinterfaces)) && !exist; i++, mapptr++)
-                       exist = (mapptr->flags != UNUSED);
-
-               if (exist) {
-                       printf("Interface Table: (In/Outvars)\n");
-                       printf("    depth ");
-                       for (j = 0; j < jd->maxinterfaces; j++) {
-                               printf("      [%2d]", j);
-                       }
-                       printf("\n");
-
-                       for (i = 0; i < 5; i++) {
-                               printf("    %5s      ",show_jit_type_names[i]);
-                               for (j = 0; j < jd->maxinterfaces; j++) {
-                                       s4 flags  = jd->interface_map[j*5+i].flags;
-                                       s4 regoff = jd->interface_map[j*5+i].regoff;
-                                       if (flags == UNUSED)
-                                               printf("  --      ");
-                                       else {
-                                               int ch;
-
-                                               if (irstage >= SHOW_REGS) {
-                                                       if (flags & SAVEDVAR) {
-                                                               if (flags & INMEMORY)
-                                                                       ch = 'M';
-                                                               else
-                                                                       ch = 'R';
-                                                       }
-                                                       else {
-                                                               if (flags & INMEMORY)
-                                                                       ch = 'm';
-                                                               else
-                                                                       ch = 'r';
-                                                       }
-                                                       printf("%c%03d(", ch, regoff);
-                                                       show_allocation(i, flags, regoff);
-                                                       printf(") ");
-                                               }
-                                               else {
-                                                       if (flags & SAVEDVAR)
-                                                               printf("  I       ");
-                                                       else
-                                                               printf("  i       ");
-                                               }
-                                       }
-                               }
-                               printf("\n");
-                       }
-                       printf("\n");
-               }
-       }
-
-       if (rd->memuse && irstage >= SHOW_REGS) {
-               int max;
-
-               max = rd->memuse;
-               printf("Stack slots: (memuse=%d", rd->memuse);
-               if (irstage >= SHOW_CODE) {
-                       printf(", stackframesize=%d", cd->stackframesize);
-                       max = cd->stackframesize;
-               }
-               printf(")\n");
-               for (i = 0; i < max; ++i) {
-#if defined(HAS_4BYTE_STACKSLOT)
-                       printf("    M%02d = 0x%02x(sp): ", i, i * 4);
-#else
-                       printf("    M%02d = 0x%02x(sp): ", i, i * 8);
-#endif
-                       for (j = 0; j < jd->vartop; ++j) {
-                               varinfo *v = VAR(j);
-                               if ((v->flags & INMEMORY) && (v->vv.regoff == i)) {
-                                       show_variable(jd, j, irstage);
-                                       putchar(' ');
-                               }
-                       }
-
-                       printf("\n");
-
-               }
-               printf("\n");
-       }
-
-#if defined(ENABLE_REPLACEMENT)
-       if (code->rplpoints) {
-               printf("Replacement Points:\n");
-               replace_show_replacement_points(code);
-               printf("\n");
-       }
-#endif /* defined(ENABLE_REPLACEMENT) */
-
-#if defined(ENABLE_DISASSEMBLER)
-       /* show code before first basic block */
-
-       if ((stage >= SHOW_CODE) && JITDATA_HAS_FLAG_SHOWDISASSEMBLE(jd)) {
-               pc = (u1 *) ((ptrint) code->mcode + cd->dseglen);
-
-               for (; pc < (u1 *) ((ptrint) code->mcode + cd->dseglen + jd->basicblocks[0].mpc);)
-                       DISASSINSTR(pc);
-
-               printf("\n");
-       }
-#endif
-
-       /* show code of all basic blocks */
-
-       for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next)
-               show_basicblock(jd, bptr, stage);
-
-#if 0 && defined(ENABLE_DISASSEMBLER)
-       /* show code after last basic block */
-
-       if (stage >= SHOW_CODE && opt_showdisassemble) {
-               printf("\nStubs code:\n");
-               printf("Length: %d\n\n", (s4) (code->mcodelength -
-                                                                          ((ptrint) cd->dseglen + lastbptr->mpc)));
-
-               pc = (u1 *) ((ptrint) code->mcode + cd->dseglen + lastbptr->mpc);
-
-               for (; (ptrint) pc < ((ptrint) code->mcode + code->mcodelength);)
-                       DISASSINSTR(pc);
-
-               printf("\n");
-       }
-#endif
-
-       Mutex_unlock(mutex);
-
-       /* finally flush the output */
-
-       fflush(stdout);
-}
-#endif /* !defined(NDEBUG) */
-
-
-#if !defined(NDEBUG) && defined(ENABLE_INLINING)
-static void show_inline_info(jitdata *jd, insinfo_inline *ii, s4 opcode, s4 stage)
-{
-       s4 *jl;
-       s4 n;
-
-       printf("(pt %d+%d+%d st ", 
-                       ii->throughcount - (ii->stackvarscount - ii->paramcount),
-                       ii->stackvarscount - ii->paramcount,
-                       ii->paramcount);
-       show_variable_array(jd, ii->stackvars, ii->stackvarscount, stage);
-
-       if (opcode == ICMD_INLINE_START || opcode == ICMD_INLINE_END) {
-               printf(" jl ");
-               jl = (opcode == ICMD_INLINE_START) ? ii->javalocals_start : ii->javalocals_end;
-               n = (opcode == ICMD_INLINE_START) ? ii->method->maxlocals : ii->outer->maxlocals;
-               show_javalocals_array(jd, jl, n, stage);
-       }
-
-       printf(") ");
-
-#if 0
-       printf("(");
-       method_print(ii->outer);
-       printf(" ==> ");
-#endif
-
-       method_print(ii->method);
-}
-#endif /* !defined(NDEBUG) && defined(ENABLE_INLINING) */
-
-
-/* show_basicblock *************************************************************
-
-   Print the intermediate representation of a basic block.
-
-   NOTE: Currently this function may only be called after register allocation!
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-void show_basicblock(jitdata *jd, basicblock *bptr, int stage)
-{
-       codeinfo    *code;
-       codegendata *cd;
-       s4           i;
-       bool         deadcode;
-       instruction *iptr;
-       int          irstage;
-#if defined(ENABLE_DISASSEMBLER)
-       methodinfo  *m;                     /* this is only a dummy               */
-       void        *pc;
-       s4           linenumber;
-       s4           currentlinenumber;
-#endif
-
-       /* get required compiler data */
-
-       code = jd->code;
-       cd   = jd->cd;
-
-       if (bptr->flags != BBDELETED) {
-#if defined(ENABLE_INTRP)
-               if (opt_intrp) {
-                       deadcode = false;
-                       irstage = SHOW_PARSE;
-               }
-               else
-#endif
-               {
-                       deadcode = (bptr->flags < BBREACHED);
-                       irstage = stage;
-               }
-
-               printf("======== %sL%03d ======== %s(flags: %d, bitflags: %01x, next: %d, type: ",
-#if defined(ENABLE_REPLACEMENT)
-                               (bptr->bitflags & BBFLAG_REPLACEMENT) ? "<REPLACE> " : 
-#endif
-                                                                                                               "",
-                          bptr->nr, 
-                          (deadcode && stage >= SHOW_STACK) ? "DEADCODE! " : "",
-                          bptr->flags, bptr->bitflags, 
-                          (bptr->next) ? (bptr->next->nr) : -1);
-
-               switch (bptr->type) {
-               case BBTYPE_STD:
-                       printf("STD");
-                       break;
-               case BBTYPE_EXH:
-                       printf("EXH");
-                       break;
-               case BBTYPE_SBR:
-                       printf("SBR");
-                       break;
-               }
-
-               printf(", icount: %d", bptr->icount);
-
-               if (irstage >= SHOW_CFG) {
-                       printf(", preds: %d [ ", bptr->predecessorcount);
-
-                       for (i = 0; i < bptr->predecessorcount; i++)
-                               printf("%d ", bptr->predecessors[i]->nr);
-
-                       printf("]");
-               }
-
-               printf("):");
-
-               if (bptr->original)
-                       printf(" (clone of L%03d)", bptr->original->nr);
-               else {
-                       basicblock *b = bptr->copied_to;
-                       if (b) {
-                               printf(" (copied to ");
-                               for (; b; b = b->copied_to)
-                                       printf("L%03d ", b->nr);
-                               printf(")");
-                       }
-               }
-
-               printf("\n");
-
-               if (irstage >= SHOW_CFG) {
-                       printf("succs: %d [ ", bptr->successorcount);
-
-                       for (i = 0; i < bptr->successorcount; i++)
-                               printf("%d ", bptr->successors[i]->nr);
-
-                       printf("]\n");
-               }
-
-               if (irstage >= SHOW_STACK) {
-                       printf("IN:  ");
-                       show_variable_array(jd, bptr->invars, bptr->indepth, irstage);
-                       printf(" javalocals: ");
-                       if (bptr->javalocals)
-                               show_javalocals_array(jd, bptr->javalocals, bptr->method->maxlocals, irstage);
-                       else
-                               printf("null");
-                       printf("\n");
-               }
-
-#if defined(ENABLE_INLINING)
-               if (bptr->inlineinfo) {
-                       printf("inlineinfo: ");
-                       show_inline_info(jd, bptr->inlineinfo, -1, irstage);
-                       printf("\n");
-               }
-#endif /* defined(ENABLE_INLINING) */
-
-#if defined(ENABLE_SSA)
-       
-               iptr = bptr->phis;
-
-               for (i = 0; i < bptr->phicount; i++, iptr++) {
-                       printf("%4d:%4d:  ", iptr->line, iptr->flags.bits >> INS_FLAG_ID_SHIFT);
-
-                       show_icmd(jd, iptr, deadcode, irstage);
-                       printf("\n");
-               }
-#endif
-
-               iptr = bptr->iinstr;
-
-               for (i = 0; i < bptr->icount; i++, iptr++) {
-                       printf("%4d:%4d:  ", iptr->line, iptr->flags.bits >> INS_FLAG_ID_SHIFT);
-
-                       show_icmd(jd, iptr, deadcode, irstage);
-                       printf("\n");
-               }
-
-               if (irstage >= SHOW_STACK) {
-                       printf("OUT: ");
-                       show_variable_array(jd, bptr->outvars, bptr->outdepth, irstage);
-                       printf("\n");
-               }
-
-#if defined(ENABLE_DISASSEMBLER)
-               if ((stage >= SHOW_CODE) && JITDATA_HAS_FLAG_SHOWDISASSEMBLE(jd) &&
-                       (!deadcode)) 
-               {
-                       printf("\n");
-                       pc         = (void *) (code->mcode + cd->dseglen + bptr->mpc);
-                       linenumber = 0;
-
-                       if (bptr->next != NULL) {
-                               for (; pc < (void *) (code->mcode + cd->dseglen + bptr->next->mpc);) {
-                                       currentlinenumber =
-                                               linenumbertable_linenumber_for_pc(&m, code, pc);
-
-                                       if (currentlinenumber != linenumber) {
-                                               linenumber = currentlinenumber;
-                                               printf("%4d:\n", linenumber);
-                                       }
-
-                                       DISASSINSTR(pc);
-                               }
-                       }
-                       else {
-                               for (; pc < (void *) (code->mcode + code->mcodelength);) {
-                                       currentlinenumber =
-                                               linenumbertable_linenumber_for_pc(&m, code, pc);
-
-                                       if (currentlinenumber != linenumber) {
-                                               linenumber = currentlinenumber;
-                                               printf("%4d:\n", linenumber);
-                                       }
-
-                                       DISASSINSTR(pc);
-                               }
-                       }
-                       printf("\n");
-               }
-#endif
-       }
-}
-#endif /* !defined(NDEBUG) */
-
-
-/* show_icmd *******************************************************************
-
-   Print the intermediate representation of an instruction.
-
-   NOTE: Currently this function may only be called after register allocation!
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-
-#define SHOW_TARGET(target)                                          \
-        if (stage >= SHOW_PARSE) {                                   \
-            printf("--> L%03d ", (target).block->nr);                \
-        }                                                            \
-        else {                                                       \
-            printf("--> insindex %d ", (target).insindex);           \
-        }
-
-#define SHOW_INT_CONST(val)                                          \
-        if (stage >= SHOW_PARSE) {                                   \
-            printf("%d (0x%08x) ", (int32_t) (val), (int32_t) (val)); \
-        }                                                            \
-        else {                                                       \
-            printf("iconst ");                                       \
-        }
-
-#if SIZEOF_VOID_P == 4
-#define SHOW_LNG_CONST(val)                                          \
-        if (stage >= SHOW_PARSE)                                     \
-            printf("%lld (0x%016llx) ", (val), (val));               \
-        else                                                         \
-            printf("lconst ");
-#else
-#define SHOW_LNG_CONST(val)                                          \
-        if (stage >= SHOW_PARSE)                                     \
-            printf("%ld (0x%016lx) ", (val), (val));                 \
-        else                                                         \
-            printf("lconst ");
-#endif
-
-#if SIZEOF_VOID_P == 4
-#define SHOW_ADR_CONST(val)                                          \
-        if (stage >= SHOW_PARSE)                                     \
-            printf("0x%08x ", (ptrint) (val));                       \
-        else                                                         \
-            printf("aconst ");
-#else
-#define SHOW_ADR_CONST(val)                                          \
-        if (stage >= SHOW_PARSE)                                     \
-            printf("0x%016lx ", (ptrint) (val));                     \
-        else                                                         \
-            printf("aconst ");
-#endif
-
-#define SHOW_FLT_CONST(val)                                          \
-        if (stage >= SHOW_PARSE) {                                   \
-            imm_union v;                                             \
-            v.f = (val);                                             \
-            printf("%g (0x%08x) ", (val), v.i);                      \
-        }                                                            \
-        else {                                                       \
-            printf("fconst ");                                       \
-        }
-
-#if SIZEOF_VOID_P == 4
-#define SHOW_DBL_CONST(val)                                          \
-        if (stage >= SHOW_PARSE) {                                   \
-            imm_union v;                                             \
-            v.d = (val);                                             \
-            printf("%g (0x%016llx) ", (val), v.l);                   \
-        }                                                            \
-        else                                                         \
-            printf("dconst ");
-#else
-#define SHOW_DBL_CONST(val)                                          \
-        if (stage >= SHOW_PARSE) {                                   \
-            imm_union v;                                             \
-            v.d = (val);                                             \
-            printf("%g (0x%016lx) ", (val), v.l);                    \
-        }                                                            \
-        else                                                         \
-            printf("dconst ");
-#endif
-
-#define SHOW_INDEX(index)                                            \
-        if (stage >= SHOW_PARSE) {                                   \
-            printf("%d ", index);                                    \
-        }                                                            \
-        else {                                                       \
-            printf("index");                                         \
-        }
-
-#define SHOW_STRING(val)                                             \
-        if (stage >= SHOW_PARSE) {                                   \
-            putchar('"');                                            \
-            utf_display_printable_ascii(                             \
-               javastring_toutf((java_handle_t *)(val), false));     \
-            printf("\" ");                                           \
-        }                                                            \
-        else {                                                       \
-            printf("string ");                                       \
-        }
-
-#define SHOW_CLASSREF_OR_CLASSINFO(c)                                \
-        if (stage >= SHOW_PARSE) {                                   \
-            if (IS_CLASSREF(c))                                      \
-                class_classref_print(c.ref);                         \
-            else                                                     \
-                class_print(c.cls);                                  \
-            putchar(' ');                                            \
-        }                                                            \
-        else {                                                       \
-            printf("class ");                                        \
-        }
-
-#define SHOW_FIELD(fmiref)                                           \
-        if (stage >= SHOW_PARSE) {                                   \
-            field_fieldref_print(fmiref);                            \
-            putchar(' ');                                            \
-        }                                                            \
-        else {                                                       \
-            printf("field ");                                        \
-        }
-
-#define SHOW_VARIABLE(v)                                             \
-    show_variable(jd, (v), stage)
-
-#define SHOW_S1(iptr)                                                \
-        if (stage >= SHOW_STACK) {                                   \
-            SHOW_VARIABLE(iptr->s1.varindex);                        \
-        }
-
-#define SHOW_S2(iptr)                                                \
-        if (stage >= SHOW_STACK) {                                   \
-            SHOW_VARIABLE(iptr->sx.s23.s2.varindex);                 \
-        }
-
-#define SHOW_S3(iptr)                                                \
-    if (stage >= SHOW_STACK) {                                       \
-        SHOW_VARIABLE(iptr->sx.s23.s3.varindex);                     \
-    }
-
-#define SHOW_DST(iptr)                                               \
-    if (stage >= SHOW_STACK) {                                       \
-        printf("=> ");                                               \
-        SHOW_VARIABLE(iptr->dst.varindex);                           \
-    }
-
-#define SHOW_S1_LOCAL(iptr)                                          \
-    if (stage >= SHOW_STACK) {                                       \
-        printf("L%d ", iptr->s1.varindex);                           \
-    }                                                                \
-    else {                                                           \
-        printf("JavaL%d ", iptr->s1.varindex);                       \
-    }
-
-#define SHOW_DST_LOCAL(iptr)                                         \
-    if (stage >= SHOW_STACK) {                                       \
-        printf("=> L%d ", iptr->dst.varindex);                       \
-    }                                                                \
-    else {                                                           \
-        printf("=> JavaL%d ", iptr->dst.varindex);                   \
-    }
-
-void show_allocation(s4 type, s4 flags, s4 regoff)
-{
-       if (type == TYPE_RET) {
-               printf("N/A");
-               return;
-       }
-
-       if (flags & INMEMORY) {
-               printf("M%02d", regoff);
-               return;
-       }
-
-#ifdef HAS_ADDRESS_REGISTER_FILE
-       if (type == TYPE_ADR) {
-               printf("R%02d", regoff);
-               return;
-       }
-#endif
-
-       if (IS_FLT_DBL_TYPE(type)) {
-               printf("F%02d", regoff);
-               return;
-       }
-
-#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
-       if (IS_2_WORD_TYPE(type)) {
-# if defined(ENABLE_JIT) && defined(ENABLE_DISASSEMBLER)
-#  if defined(ENABLE_INTRP)
-               if (opt_intrp)
-                       printf("%3d/%3d", GET_LOW_REG(regoff),
-                                       GET_HIGH_REG(regoff));
-               else
-#  endif
-                       printf("%3s/%3s", abi_registers_integer_name[GET_LOW_REG(regoff)],
-                                  abi_registers_integer_name[GET_HIGH_REG(regoff)]);
-# else
-               printf("%3d/%3d", GET_LOW_REG(regoff),
-                          GET_HIGH_REG(regoff));
-# endif
-               return;
-       } 
-#endif /* defined(SUPPORT_COMBINE_INTEGER_REGISTERS) */
-
-#if defined(ENABLE_JIT) && defined(ENABLE_DISASSEMBLER)
-# if defined(ENABLE_INTRP)
-       if (opt_intrp)
-               printf("%3d", regoff);
-       else
-# endif
-               printf("%3s", abi_registers_integer_name[regoff]);
-#else
-       printf("%3d", regoff);
-#endif
-}
-
-void show_variable(jitdata *jd, s4 index, int stage)
-{
-       show_variable_intern(jd, index, stage);
-       putchar(' ');
-}
-
-static void show_variable_intern(jitdata *jd, s4 index, int stage)
-{
-       char type;
-       char kind;
-       varinfo *v;
-
-       if (index < 0 || index >= jd->vartop) {
-               printf("<INVALID INDEX:%d>", index);
-               return;
-       }
-
-       v = VAR(index);
-
-       switch (v->type) {
-               case TYPE_INT: type = 'i'; break;
-               case TYPE_LNG: type = 'l'; break;
-               case TYPE_FLT: type = 'f'; break;
-               case TYPE_DBL: type = 'd'; break;
-               case TYPE_ADR: type = 'a'; break;
-               case TYPE_RET: type = 'r'; break;
-               default:       type = '?';
-       }
-
-       if (index < jd->localcount) {
-               kind = 'L';
-               if (v->flags & (PREALLOC | INOUT))
-                               printf("<INVALID FLAGS!>");
-       }
-       else {
-               if (v->flags & PREALLOC) {
-                       kind = 'A';
-                       if (v->flags & INOUT) {
-                               /* PREALLOC is used to avoid allocation of TYPE_RET */
-                               if (v->type == TYPE_RET)
-                                       kind = 'i';
-                               else
-                                       printf("<INVALID FLAGS!>");
-                       }
-               }
-               else if (v->flags & INOUT)
-                       kind = 'I';
-               else
-                       kind = 'T';
-       }
-
-       printf("%c%c%d", kind, type, index);
-
-       if (v->flags & SAVEDVAR)
-               putchar('!');
-
-       if (stage >= SHOW_REGS || (v->flags & PREALLOC)) {
-               putchar('(');
-               show_allocation(v->type, v->flags, v->vv.regoff);
-               putchar(')');
-       }
-
-       if (v->type == TYPE_RET && (v->flags & PREALLOC)) {
-               printf("(L%03d)", v->vv.retaddr->nr);
-       }
-}
-
-static void show_variable_array_intern(jitdata *jd, s4 *vars, int n, int stage,
-                                                                          bool javalocals)
-{
-       int i;
-       int nr;
-
-       if (vars == NULL) {
-               printf("<null>");
-               return;
-       }
-
-       printf("[");
-       for (i=0; i<n; ++i) {
-               if (i)
-                       putchar(' ');
-               if (vars[i] < 0) {
-                       if (vars[i] == UNUSED)
-                               putchar('-');
-                       else if (javalocals) {
-                               nr = RETADDR_FROM_JAVALOCAL(vars[i]);
-                               printf("ret(L%03d)", nr);
-                       }
-                       else {
-                               printf("<INVALID INDEX:%d>", vars[i]);
-                       }
-               }
-               else
-                       show_variable_intern(jd, vars[i], stage);
-       }
-       printf("]");
-}
-
-void show_variable_array(jitdata *jd, s4 *vars, int n, int stage)
-{
-       show_variable_array_intern(jd, vars, n, stage, false);
-}
-
-void show_javalocals_array(jitdata *jd, s4 *vars, int n, int stage)
-{
-       show_variable_array_intern(jd, vars, n, stage, true);
-}
-
-void show_icmd(jitdata *jd, instruction *iptr, bool deadcode, int stage)
-{
-       u2                 opcode;
-       branch_target_t   *table;
-       lookup_target_t   *lookup;
-       constant_FMIref   *fmiref;
-       s4                *argp;
-       s4                 i;
-
-       /* get the opcode and the condition */
-
-       opcode    =  iptr->opc;
-
-       printf("%s ", icmd_table[opcode].name);
-
-       if (stage < SHOW_PARSE)
-               return;
-
-       if (deadcode)
-               stage = SHOW_PARSE;
-
-       /* Print the condition for conditional instructions. */
-
-       /* XXX print condition from flags */
-
-       if (iptr->flags.bits & INS_FLAG_UNRESOLVED)
-               printf("(UNRESOLVED) ");
-
-       switch (opcode) {
-
-       case ICMD_POP:
-       case ICMD_CHECKNULL:
-               SHOW_S1(iptr);
-               break;
-
-               /* unary */
-       case ICMD_ARRAYLENGTH:
-       case ICMD_INEG:
-       case ICMD_LNEG:
-       case ICMD_FNEG:
-       case ICMD_DNEG:
-       case ICMD_I2L:
-       case ICMD_I2F:
-       case ICMD_I2D:
-       case ICMD_L2I:
-       case ICMD_L2F:
-       case ICMD_L2D:
-       case ICMD_F2I:
-       case ICMD_F2L:
-       case ICMD_F2D:
-       case ICMD_D2I:
-       case ICMD_D2L:
-       case ICMD_D2F:
-       case ICMD_INT2BYTE:
-       case ICMD_INT2CHAR:
-       case ICMD_INT2SHORT:
-               SHOW_S1(iptr);
-               SHOW_DST(iptr);
-               break;
-
-               /* binary */
-       case ICMD_IADD:
-       case ICMD_LADD:
-       case ICMD_FADD:
-       case ICMD_DADD:
-       case ICMD_ISUB:
-       case ICMD_LSUB:
-       case ICMD_FSUB:
-       case ICMD_DSUB:
-       case ICMD_IMUL:
-       case ICMD_LMUL:
-       case ICMD_FMUL:
-       case ICMD_DMUL:
-       case ICMD_IDIV:
-       case ICMD_LDIV:
-       case ICMD_FDIV:
-       case ICMD_DDIV:
-       case ICMD_IREM:
-       case ICMD_LREM:
-       case ICMD_FREM:
-       case ICMD_DREM:
-       case ICMD_ISHL:
-       case ICMD_LSHL:
-       case ICMD_ISHR:
-       case ICMD_LSHR:
-       case ICMD_IUSHR:
-       case ICMD_LUSHR:
-       case ICMD_IAND:
-       case ICMD_LAND:
-       case ICMD_IOR:
-       case ICMD_LOR:
-       case ICMD_IXOR:
-       case ICMD_LXOR:
-       case ICMD_LCMP:
-       case ICMD_FCMPL:
-       case ICMD_FCMPG:
-       case ICMD_DCMPL:
-       case ICMD_DCMPG:
-               SHOW_S1(iptr);
-               SHOW_S2(iptr);
-               SHOW_DST(iptr);
-               break;
-
-               /* binary/const INT */
-       case ICMD_IADDCONST:
-       case ICMD_ISUBCONST:
-       case ICMD_IMULCONST:
-       case ICMD_IMULPOW2:
-       case ICMD_IDIVPOW2:
-       case ICMD_IREMPOW2:
-       case ICMD_IANDCONST:
-       case ICMD_IORCONST:
-       case ICMD_IXORCONST:
-       case ICMD_ISHLCONST:
-       case ICMD_ISHRCONST:
-       case ICMD_IUSHRCONST:
-       case ICMD_LSHLCONST:
-       case ICMD_LSHRCONST:
-       case ICMD_LUSHRCONST:
-               SHOW_S1(iptr);
-               SHOW_INT_CONST(iptr->sx.val.i); 
-               SHOW_DST(iptr);
-               break;
-
-               /* ?ASTORECONST (trinary/const INT) */
-       case ICMD_IASTORECONST:
-       case ICMD_BASTORECONST:
-       case ICMD_CASTORECONST:
-       case ICMD_SASTORECONST:
-               SHOW_S1(iptr);
-               SHOW_S2(iptr);
-               SHOW_INT_CONST(iptr->sx.s23.s3.constval);
-               break;
-
-               /* const INT */
-       case ICMD_ICONST:
-               SHOW_INT_CONST(iptr->sx.val.i); 
-               SHOW_DST(iptr);
-               break;
-
-               /* binary/const LNG */
-       case ICMD_LADDCONST:
-       case ICMD_LSUBCONST:
-       case ICMD_LMULCONST:
-       case ICMD_LMULPOW2:
-       case ICMD_LDIVPOW2:
-       case ICMD_LREMPOW2:
-       case ICMD_LANDCONST:
-       case ICMD_LORCONST:
-       case ICMD_LXORCONST:
-               SHOW_S1(iptr);
-               SHOW_LNG_CONST(iptr->sx.val.l);
-               SHOW_DST(iptr);
-               break;
-
-               /* trinary/const LNG (<= pointer size) */
-       case ICMD_LASTORECONST:
-               SHOW_S1(iptr);
-               SHOW_S2(iptr);
-               SHOW_ADR_CONST(iptr->sx.s23.s3.constval);
-               break;
-
-               /* const LNG */
-       case ICMD_LCONST:
-               SHOW_LNG_CONST(iptr->sx.val.l); 
-               SHOW_DST(iptr);
-               break;
-
-               /* const FLT */
-       case ICMD_FCONST:
-               SHOW_FLT_CONST(iptr->sx.val.f); 
-               SHOW_DST(iptr);
-               break;
-
-               /* const DBL */
-       case ICMD_DCONST:
-               SHOW_DBL_CONST(iptr->sx.val.d); 
-               SHOW_DST(iptr);
-               break;
-
-               /* const ADR */
-       case ICMD_ACONST:
-               if (iptr->flags.bits & INS_FLAG_CLASS) {
-                       SHOW_ADR_CONST(iptr->sx.val.anyptr);
-                       SHOW_CLASSREF_OR_CLASSINFO(iptr->sx.val.c);
-               }
-               else if (iptr->sx.val.anyptr == NULL) {
-                       printf("NULL ");
-               }
-               else {
-                       SHOW_ADR_CONST(iptr->sx.val.anyptr);
-                       SHOW_STRING(iptr->sx.val.stringconst);
-               }
-               SHOW_DST(iptr);
-               break;
-
-       case ICMD_AASTORECONST:
-               SHOW_S1(iptr);
-               SHOW_S2(iptr);
-               printf("%p ", (void*) iptr->sx.s23.s3.constval);
-               break;
-
-       case ICMD_GETFIELD:        /* 1 -> 1 */
-       case ICMD_PUTFIELD:        /* 2 -> 0 */
-       case ICMD_PUTSTATIC:       /* 1 -> 0 */
-       case ICMD_GETSTATIC:       /* 0 -> 1 */
-       case ICMD_PUTSTATICCONST:  /* 0 -> 0 */
-       case ICMD_PUTFIELDCONST:   /* 1 -> 0 */
-               if (opcode != ICMD_GETSTATIC && opcode != ICMD_PUTSTATICCONST) {
-                       SHOW_S1(iptr);
-                       if (opcode == ICMD_PUTFIELD) {
-                               SHOW_S2(iptr);
-                       }
-               }
-               INSTRUCTION_GET_FIELDREF(iptr, fmiref);
-               SHOW_FIELD(fmiref);
-
-               if (opcode == ICMD_GETSTATIC || opcode == ICMD_GETFIELD) {
-                       SHOW_DST(iptr);
-               }
-               break;
-
-       case ICMD_IINC:
-               SHOW_S1_LOCAL(iptr);
-               SHOW_INT_CONST(iptr->sx.val.i);
-               SHOW_DST_LOCAL(iptr);
-               break;
-
-       case ICMD_IASTORE:
-       case ICMD_SASTORE:
-       case ICMD_BASTORE:
-       case ICMD_CASTORE:
-       case ICMD_LASTORE:
-       case ICMD_DASTORE:
-       case ICMD_FASTORE:
-       case ICMD_AASTORE:
-               SHOW_S1(iptr);
-               SHOW_S2(iptr);
-               SHOW_S3(iptr);
-               break;
-
-       case ICMD_IALOAD:
-       case ICMD_SALOAD:
-       case ICMD_BALOAD:
-       case ICMD_CALOAD:
-       case ICMD_LALOAD:
-       case ICMD_DALOAD:
-       case ICMD_FALOAD:
-       case ICMD_AALOAD:
-               SHOW_S1(iptr);
-               SHOW_S2(iptr);
-               SHOW_DST(iptr);
-               break;
-
-       case ICMD_RET:
-               SHOW_S1_LOCAL(iptr);
-               if (stage >= SHOW_STACK) {
-                       printf(" ---> L%03d", iptr->dst.block->nr);
-               }
-               break;
-
-       case ICMD_ILOAD:
-       case ICMD_LLOAD:
-       case ICMD_FLOAD:
-       case ICMD_DLOAD:
-       case ICMD_ALOAD:
-               SHOW_S1_LOCAL(iptr);
-               SHOW_DST(iptr);
-               break;
-
-       case ICMD_ISTORE:
-       case ICMD_LSTORE:
-       case ICMD_FSTORE:
-       case ICMD_DSTORE:
-       case ICMD_ASTORE:
-               SHOW_S1(iptr);
-               SHOW_DST_LOCAL(iptr);
-               if (stage >= SHOW_STACK && iptr->sx.s23.s3.javaindex != UNUSED)
-                       printf(" (javaindex %d)", iptr->sx.s23.s3.javaindex);
-               if (iptr->flags.bits & INS_FLAG_RETADDR) {
-                       printf(" (retaddr L%03d)", RETADDR_FROM_JAVALOCAL(iptr->sx.s23.s2.retaddrnr));
-               }
-               break;
-
-       case ICMD_NEW:
-               SHOW_DST(iptr);
-               break;
-
-       case ICMD_NEWARRAY:
-               SHOW_DST(iptr);
-               break;
-
-       case ICMD_ANEWARRAY:
-               SHOW_DST(iptr);
-               break;
-
-       case ICMD_MULTIANEWARRAY:
-               if (stage >= SHOW_STACK) {
-                       argp = iptr->sx.s23.s2.args;
-                       i = iptr->s1.argcount;
-                       while (i--) {
-                               SHOW_VARIABLE(*(argp++));
-                       }
-               }
-               else {
-                       printf("argcount=%d ", iptr->s1.argcount);
-               }
-               class_classref_or_classinfo_print(iptr->sx.s23.s3.c);
-               putchar(' ');
-               SHOW_DST(iptr);
-               break;
-
-       case ICMD_CHECKCAST:
-               SHOW_S1(iptr);
-               class_classref_or_classinfo_print(iptr->sx.s23.s3.c);
-               putchar(' ');
-               SHOW_DST(iptr);
-               break;
-
-       case ICMD_INSTANCEOF:
-               SHOW_S1(iptr);
-               SHOW_DST(iptr);
-               break;
-
-       case ICMD_INLINE_START:
-       case ICMD_INLINE_END:
-       case ICMD_INLINE_BODY:
-#if defined(ENABLE_INLINING)
-               {
-                       insinfo_inline *ii = iptr->sx.s23.s3.inlineinfo;
-                       show_inline_info(jd, ii, opcode, stage);
-               }
-#endif
-               break;
-
-       case ICMD_BUILTIN:
-               if (stage >= SHOW_STACK) {
-                       argp = iptr->sx.s23.s2.args;
-                       i = iptr->s1.argcount;
-                       while (i--) {
-                               if ((iptr->s1.argcount - 1 - i) == iptr->sx.s23.s3.bte->md->paramcount)
-                                       printf(" pass-through: ");
-                               SHOW_VARIABLE(*(argp++));
-                       }
-               }
-               printf("%s ", iptr->sx.s23.s3.bte->cname);
-               if (iptr->sx.s23.s3.bte->md->returntype.type != TYPE_VOID) {
-                       SHOW_DST(iptr);
-               }
-               break;
-
-       case ICMD_INVOKEVIRTUAL:
-       case ICMD_INVOKESPECIAL:
-       case ICMD_INVOKESTATIC:
-       case ICMD_INVOKEINTERFACE:
-               if (stage >= SHOW_STACK) {
-                       methoddesc *md;
-                       INSTRUCTION_GET_METHODDESC(iptr, md);
-                       argp = iptr->sx.s23.s2.args;
-                       i = iptr->s1.argcount;
-                       while (i--) {
-                               if ((iptr->s1.argcount - 1 - i) == md->paramcount)
-                                       printf(" pass-through: ");
-                               SHOW_VARIABLE(*(argp++));
-                       }
-               }
-               INSTRUCTION_GET_METHODREF(iptr, fmiref);
-               method_methodref_print(fmiref);
-               if (fmiref->parseddesc.md->returntype.type != TYPE_VOID) {
-                       putchar(' ');
-                       SHOW_DST(iptr);
-               }
-               break;
-
-       case ICMD_IFEQ:
-       case ICMD_IFNE:
-       case ICMD_IFLT:
-       case ICMD_IFGE:
-       case ICMD_IFGT:
-       case ICMD_IFLE:
-               SHOW_S1(iptr);
-               SHOW_INT_CONST(iptr->sx.val.i); 
-               SHOW_TARGET(iptr->dst);
-               break;
-
-       case ICMD_IF_LEQ:
-       case ICMD_IF_LNE:
-       case ICMD_IF_LLT:
-       case ICMD_IF_LGE:
-       case ICMD_IF_LGT:
-       case ICMD_IF_LLE:
-               SHOW_S1(iptr);
-               SHOW_LNG_CONST(iptr->sx.val.l); 
-               SHOW_TARGET(iptr->dst);
-               break;
-
-       case ICMD_GOTO:
-               SHOW_TARGET(iptr->dst);
-               break;
-
-       case ICMD_JSR:
-               SHOW_TARGET(iptr->sx.s23.s3.jsrtarget);
-               SHOW_DST(iptr);
-               break;
-
-       case ICMD_IFNULL:
-       case ICMD_IFNONNULL:
-               SHOW_S1(iptr);
-               SHOW_TARGET(iptr->dst);
-               break;
-
-       case ICMD_IF_ICMPEQ:
-       case ICMD_IF_ICMPNE:
-       case ICMD_IF_ICMPLT:
-       case ICMD_IF_ICMPGE:
-       case ICMD_IF_ICMPGT:
-       case ICMD_IF_ICMPLE:
-
-       case ICMD_IF_LCMPEQ:
-       case ICMD_IF_LCMPNE:
-       case ICMD_IF_LCMPLT:
-       case ICMD_IF_LCMPGE:
-       case ICMD_IF_LCMPGT:
-       case ICMD_IF_LCMPLE:
-
-       case ICMD_IF_ACMPEQ:
-       case ICMD_IF_ACMPNE:
-               SHOW_S1(iptr);
-               SHOW_S2(iptr);
-               SHOW_TARGET(iptr->dst);
-               break;
-
-       case ICMD_TABLESWITCH:
-               SHOW_S1(iptr);
-               table = iptr->dst.table;
-
-               i = iptr->sx.s23.s3.tablehigh - iptr->sx.s23.s2.tablelow + 1;
-
-               printf("high=%d low=%d count=%d\n", iptr->sx.s23.s3.tablehigh, iptr->sx.s23.s2.tablelow, i);
-               while (--i >= 0) {
-                       printf("\t\t%d --> ", (int) (table - iptr->dst.table));
-                       printf("L%03d\n", table->block->nr);
-                       table++;
-               }
-
-               break;
-
-       case ICMD_LOOKUPSWITCH:
-               SHOW_S1(iptr);
-
-               printf("count=%d, default=L%03d\n",
-                          iptr->sx.s23.s2.lookupcount,
-                          iptr->sx.s23.s3.lookupdefault.block->nr);
-
-               lookup = iptr->dst.lookup;
-               i = iptr->sx.s23.s2.lookupcount;
-
-               while (--i >= 0) {
-                       printf("\t\t%d --> L%03d\n",
-                                  lookup->value,
-                                  lookup->target.block->nr);
-                       lookup++;
-               }
-               break;
-
-       case ICMD_FRETURN:
-       case ICMD_IRETURN:
-       case ICMD_DRETURN:
-       case ICMD_LRETURN:
-               SHOW_S1(iptr);
-               break;
-
-       case ICMD_ARETURN:
-       case ICMD_ATHROW:
-               SHOW_S1(iptr);
-               if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                       /* XXX this needs more work */
-#if 0
-                       unresolved_class_debug_dump(iptr->sx.s23.s2.uc, stdout);
-#endif
-               }
-               break;
-
-       case ICMD_COPY:
-       case ICMD_MOVE:
-               SHOW_S1(iptr);
-               SHOW_DST(iptr);
-               break;
-       case ICMD_GETEXCEPTION:
-               SHOW_DST(iptr);
-               break;
-#if defined(ENABLE_SSA)        
-       case ICMD_PHI:
-               printf("[ ");
-               for (i = 0; i < iptr->s1.argcount; ++i) {
-                       SHOW_VARIABLE(iptr->sx.s23.s2.iargs[i]->dst.varindex);
-               }
-               printf("] ");
-               SHOW_DST(iptr);
-               if (iptr->flags.bits & (1 << 0)) printf("used ");
-               if (iptr->flags.bits & (1 << 1)) printf("redundantAll ");
-               if (iptr->flags.bits & (1 << 2)) printf("redundantOne ");
-               break;
-#endif
-       }
-       fflush(stdout);
-}
-#endif /* !defined(NDEBUG) */
-
-/* Debug output filtering */
-
-#if defined(ENABLE_DEBUG_FILTER)
-
-#if !defined(ENABLE_THREADS)
-u2 _no_threads_filterverbosecallctr[2] = { 0, 0 };
-#endif
-
-struct show_filter {
-       /* Boolean indicating if filter is enabled. */
-       u1 enabled;
-       /* Regular expression the method name is matched against */
-       regex_t regex;
-       /* Flag set on m->filtermatches if regex matches */
-       u1 flag;
-};
-
-typedef struct show_filter show_filter_t;
-
-#define SHOW_FILTERS_SIZE 3
-
-/* Array of filters applyed on a method */
-static struct show_filter show_filters[SHOW_FILTERS_SIZE];
-
-static void show_filter_init(show_filter_t *cf, const char *str, u1 flag, u1 default_flag, const char *description) {
-       int err;
-       char err_buf[128];
-
-       if (str) {
-               err = regcomp(&cf->regex, str, REG_EXTENDED | REG_NOSUB);
-               if (err != 0) {
-                       regerror(err, &cf->regex, err_buf, sizeof(err_buf));
-                       vm_abort(
-                               "Invalid value given for %s: `%s' (%s).", 
-                               description, str, err_buf
-                       );
-               }
-               cf->flag = flag;
-               cf->enabled = 1;
-       } else {
-               cf->flag = default_flag;
-               cf->enabled = 0;
-       }
-}
-
-void show_filters_init(void) {
-
-       show_filter_init(
-               show_filters + 0,
-               opt_filter_verbosecall_include,
-               SHOW_FILTER_FLAG_VERBOSECALL_INCLUDE,
-               SHOW_FILTER_FLAG_VERBOSECALL_INCLUDE,
-               "verbose call include filter"
-       );
-
-       show_filter_init(
-               show_filters + 1,
-               opt_filter_verbosecall_exclude,
-               SHOW_FILTER_FLAG_VERBOSECALL_EXCLUDE,
-               0,
-               "verbose call exclude filter"
-       );
-
-       show_filter_init(
-               show_filters + 2,
-               opt_filter_show_method,
-               SHOW_FILTER_FLAG_SHOW_METHOD,
-               SHOW_FILTER_FLAG_SHOW_METHOD,
-               "show method filter"
-       );
-}
-
-/*
- (Pseudo)State machine:
-
- States are INITIAL, INCLUDE1, INCLUDE2, ..., EXCLUDE1, ..., EXCLUDE2, ...
-
-                                                        Enter              Enter
- Enter                                                  Include            Include
- Exclude                                                  | |                | |
-  | |    Enter              Enter              Enter      | |     Enter      | |
-  | |    Include            Include            Exclude    | |     Exclude    | |
-  | v   --------->        ---------->        ---------->  | v   ---------->  | v
-INITIAL           INCLUDE1           INCLUDE2           EXCLUDE1           EXCLUDE2
-  | ^   <---------        <----------        <----------  | ^   <----------  | ^
-  | |    Exit               Exit               Exit       | |     Exit       | |
-  | |    Include            Include            Exclude    | |     Exclude    | |
-  | |                                                     | |                | |
- Exit                                                    Exit               Exit
- Exclude                                                 Include            Include
-
-  Verbose call scope is active if we are in a INCLUDE state.
-
-  State encoding:
-
-  INITIAL: ctr[0] == 0, ctr[1] == 0
-  INCLUDEN: ctr[1] == N, ctr[1] == 0
-  EXCLUDEN: ctr[1] == N
-*/
-
-void show_filters_apply(methodinfo *m) {
-       int i;
-       int res;
-       char *method_name;
-       s4 len;
-       int32_t dumpmarker;
-
-       /* compose full name of method */
-
-       len = 
-               utf_bytes(m->clazz->name) +
-               1 +
-               utf_bytes(m->name) +
-               utf_bytes(m->descriptor) +
-               1;
-
-       DMARKER;
-
-       method_name = DMNEW(char, len);
-
-       utf_cat_classname(method_name, m->clazz->name);
-       strcat(method_name, ".");
-       utf_cat(method_name, m->name);
-       utf_cat(method_name, m->descriptor);
-
-       /* reset all flags */
-
-       m->filtermatches = 0;
-
-       for (i = 0; i < SHOW_FILTERS_SIZE; ++i) {
-               if (show_filters[i].enabled) {
-
-                       res = regexec(&show_filters[i].regex, method_name, 0, NULL, 0);
-
-                       if (res == 0) {
-                               m->filtermatches |= show_filters[i].flag;
-                       }
-               } else {
-                       /* Default is to show all */
-                       m->filtermatches |= show_filters[i].flag;
-               }
-       }
-
-       /* release memory */
-
-       DRELEASE; 
-}
-
-#define STATE_IS_INITIAL() ((FILTERVERBOSECALLCTR[0] == 0) && (FILTERVERBOSECALLCTR[1] == 0))
-#define STATE_IS_INCLUDE() ((FILTERVERBOSECALLCTR[0] > 0) && (FILTERVERBOSECALLCTR[1] == 0))
-#define STATE_IS_EXCLUDE() (FILTERVERBOSECALLCTR[1] > 0)
-#define EVENT_INCLUDE() (m->filtermatches & SHOW_FILTER_FLAG_VERBOSECALL_INCLUDE)
-#define EVENT_EXCLUDE() (m->filtermatches & SHOW_FILTER_FLAG_VERBOSECALL_EXCLUDE)
-#define TRANSITION_NEXT_INCLUDE() ++FILTERVERBOSECALLCTR[0]
-#define TRANSITION_PREV_INCLUDE() --FILTERVERBOSECALLCTR[0]
-#define TRANSITION_NEXT_EXCLUDE() ++FILTERVERBOSECALLCTR[1]
-#define TRANSITION_PREV_EXCLUDE() --FILTERVERBOSECALLCTR[1]
-
-#if 0
-void dump_state() {
-       if (STATE_IS_INITIAL()) printf("<INITIAL>\n");
-       else if (STATE_IS_INCLUDE()) printf("<INCLUDE %hd>\n", FILTERVERBOSECALLCTR[0]);
-       else if (STATE_IS_EXCLUDE()) printf("<EXCLUDE %hd>\n", FILTERVERBOSECALLCTR[1]);
-}
-#endif
-
-int show_filters_test_verbosecall_enter(methodinfo *m) {
-
-       int force_show = 0;
-
-       if (STATE_IS_INITIAL()) {
-               if (EVENT_INCLUDE()) {
-                       TRANSITION_NEXT_INCLUDE();
-               }
-       } else if (STATE_IS_INCLUDE()) {
-               if (EVENT_EXCLUDE()) {
-                       TRANSITION_NEXT_EXCLUDE();
-                       /* just entered exclude, show this method */
-                       force_show = 1;
-               } else if (EVENT_INCLUDE()) {
-                       TRANSITION_NEXT_INCLUDE();
-               }
-       } else if (STATE_IS_EXCLUDE()) {
-               if (EVENT_EXCLUDE()) {
-                       TRANSITION_NEXT_EXCLUDE();
-               }
-       }
-
-       return STATE_IS_INCLUDE() || force_show;
-}
-
-int show_filters_test_verbosecall_exit(methodinfo *m) {
-
-       int force_show = 0;
-
-       if (m) {
-               if (STATE_IS_INCLUDE()) {
-                       if (EVENT_INCLUDE()) {
-                               TRANSITION_PREV_INCLUDE();
-                               /* just entered initial, show this method */
-                               if (STATE_IS_INITIAL()) force_show = 1;
-                       }
-           } else if (STATE_IS_EXCLUDE()) {
-                       if (EVENT_EXCLUDE()) {
-                               TRANSITION_PREV_EXCLUDE();
-                       }
-               }
-       }
-
-       return STATE_IS_INCLUDE() || force_show;
-}
-
-#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:
- */
diff --git a/src/vm/jit/show.cpp b/src/vm/jit/show.cpp
new file mode 100644 (file)
index 0000000..d4dad98
--- /dev/null
@@ -0,0 +1,1667 @@
+/* src/vm/jit/show.cpp - showing the intermediate representation
+
+   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 "threads/lock.hpp"
+
+#include "vm/global.h"
+#include "vm/jit/builtin.hpp"
+#include "vm/options.h"
+#include "vm/string.hpp"
+#include "vm/vm.hpp"
+
+#include "vm/jit/abi.h"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/show.hpp"
+#include "vm/jit/disass.h"
+#include "vm/jit/stack.h"
+#include "vm/jit/parse.h"
+
+#if defined(ENABLE_DEBUG_FILTER)
+# include <sys/types.h>
+# include <regex.h>
+# include "threads/thread.hpp"
+#endif
+
+
+/* global variables ***********************************************************/
+
+#if !defined(NDEBUG)
+static Mutex mutex;
+#endif
+
+
+/* prototypes *****************************************************************/
+
+#if !defined(NDEBUG)
+static void show_variable_intern(jitdata *jd, s4 index, int stage);
+#endif
+
+
+/* show_init *******************************************************************
+
+   Initialized the show subsystem (called by jit_init).
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+bool show_init(void)
+{
+#if defined(ENABLE_DEBUG_FILTER)
+       show_filters_init();
+#endif
+
+       /* everything's ok */
+
+       return true;
+}
+#endif
+
+
+#if !defined(NDEBUG)
+const char *show_jit_type_names[] = {
+       "INT",
+       "LNG",
+       "FLT",
+       "DBL",
+       "ADR",
+       "??5",
+       "??6",
+       "??7",
+       "RET"
+};
+
+const char show_jit_type_letters[] = {
+       'I',
+       'L',
+       'F',
+       'D',
+       'A',
+       '5',
+       '6',
+       '7',
+       'R'
+};
+#endif
+
+
+/* show_method *****************************************************************
+
+   Print the intermediate representation of a method.
+
+   NOTE: Currently this function may only be called after register allocation!
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void show_method(jitdata *jd, int stage)
+{
+       methodinfo     *m;
+       codeinfo       *code;
+       codegendata    *cd;
+       registerdata   *rd;
+       basicblock     *bptr;
+       basicblock     *lastbptr;
+       exception_entry *ex;
+       s4              i, j;
+       int             irstage;
+#if defined(ENABLE_DISASSEMBLER)
+       u1             *pc;
+#endif
+
+       /* get required compiler data */
+
+       m    = jd->m;
+       code = jd->code;
+       cd   = jd->cd;
+       rd   = jd->rd;
+
+       // We need to enter a lock here, since the binutils disassembler
+       // is not reentrant-able and we could not read functions printed
+       // at the same time.
+       mutex.lock();
+
+#if defined(ENABLE_INTRP)
+       if (opt_intrp)
+               irstage = SHOW_PARSE;
+       else
+#endif
+               irstage = stage;
+
+       /* get the last basic block */
+
+       for (lastbptr = jd->basicblocks; lastbptr->next != NULL; lastbptr = lastbptr->next);
+
+       printf("\n");
+
+       method_println(m);
+
+       if (code_is_leafmethod(code))
+               printf("LEAFMETHOD\n");
+
+       printf("\nBasic blocks: %d\n", jd->basicblockcount);
+       if (stage >= SHOW_CODE) {
+               printf("Code length:  %d\n", (lastbptr->mpc - jd->basicblocks[0].mpc));
+               printf("Data length:  %d\n", cd->dseglen);
+               printf("Stub length:  %d\n", (s4) (code->mcodelength -
+                                                                                  ((ptrint) cd->dseglen + lastbptr->mpc)));
+       }
+       printf("Variables:       %d (%d used)\n", jd->varcount, jd->vartop);
+       if (stage >= SHOW_STACK)
+               printf("Max interfaces:  %d\n", jd->maxinterfaces);
+       printf("Max locals:      %d\n", jd->maxlocals);
+       printf("Max stack:       %d\n", m->maxstack);
+       printf("Linenumbers:     %d\n", m->linenumbercount);
+       printf("Branch to entry: %s\n", (jd->branchtoentry) ? "yes" : "no");
+       printf("Branch to end:   %s\n", (jd->branchtoend) ? "yes" : "no");
+       if (stage >= SHOW_STACK) {
+               printf("Number of RETURNs: %d", jd->returncount);
+               if (jd->returncount == 1)
+                       printf(" (block L%03d)", jd->returnblock->nr);
+               printf("\n");
+       }
+
+       if (stage >= SHOW_PARSE) {
+               printf("Exceptions (Number: %d):\n", jd->exceptiontablelength);
+               for (ex = jd->exceptiontable; ex != NULL; ex = ex->down) {
+                       printf("    L%03d ... ", ex->start->nr );
+                       printf("L%03d  = ", ex->end->nr);
+                       printf("L%03d", ex->handler->nr);
+                       printf("  (catchtype: ");
+                       if (ex->catchtype.any)
+                               if (IS_CLASSREF(ex->catchtype))
+                                       class_classref_print(ex->catchtype.ref);
+                               else
+                                       class_print(ex->catchtype.cls);
+                       else
+                               printf("ANY");
+                       printf(")\n");
+               }
+       }
+       
+       if (irstage >= SHOW_PARSE && rd && jd->localcount > 0) {
+               printf("Local Table:\n");
+               for (i = 0; i < jd->localcount; i++) {
+                       printf("   %3d: ", i);
+
+#if defined(ENABLE_JIT) && defined(ENABLE_DISASSEMBLER)
+# if defined(ENABLE_INTRP)
+                       if (!opt_intrp) {
+# endif
+                               printf("   (%s) ", show_jit_type_names[VAR(i)->type]);
+                               if (irstage >= SHOW_REGS)
+                                       show_allocation(VAR(i)->type, VAR(i)->flags, VAR(i)->vv.regoff);
+                               printf("\n");
+# if defined(ENABLE_INTRP)
+                       }
+# endif
+#endif /* defined(ENABLE_JIT) && defined(ENABLE_DISASSEMBLER) */
+               }
+               printf("\n");
+       }
+
+       if (jd->maxlocals > 0 && jd->local_map != NULL) {
+               printf("Local Map:\n");
+               printf("    index ");
+               for (j = 0; j < jd->maxlocals; j++) {
+                       printf(" [%2d]", j);
+               }
+               printf("\n");
+               for (i = 0; i < 5; i++) {
+                       printf("    %5s ",show_jit_type_names[i]);
+                       for (j = 0; j < jd->maxlocals; j++) {
+                               if (jd->local_map[j*5+i] == UNUSED)
+                                       printf("  -- ");
+                               else
+                                       printf("%4i ",jd->local_map[j*5+i]);
+                       }
+                       printf("\n");
+               }
+               printf("\n");
+       }
+
+       if (jd->maxinterfaces > 0 && jd->interface_map && irstage >= SHOW_STACK) {
+               bool exist = false;
+               interface_info *mapptr = jd->interface_map;
+               
+               /* look if there exist any INOUTS */
+               for (i = 0; (i < (5 * jd->maxinterfaces)) && !exist; i++, mapptr++)
+                       exist = (mapptr->flags != UNUSED);
+
+               if (exist) {
+                       printf("Interface Table: (In/Outvars)\n");
+                       printf("    depth ");
+                       for (j = 0; j < jd->maxinterfaces; j++) {
+                               printf("      [%2d]", j);
+                       }
+                       printf("\n");
+
+                       for (i = 0; i < 5; i++) {
+                               printf("    %5s      ",show_jit_type_names[i]);
+                               for (j = 0; j < jd->maxinterfaces; j++) {
+                                       s4 flags  = jd->interface_map[j*5+i].flags;
+                                       s4 regoff = jd->interface_map[j*5+i].regoff;
+                                       if (flags == UNUSED)
+                                               printf("  --      ");
+                                       else {
+                                               int ch;
+
+                                               if (irstage >= SHOW_REGS) {
+                                                       if (flags & SAVEDVAR) {
+                                                               if (flags & INMEMORY)
+                                                                       ch = 'M';
+                                                               else
+                                                                       ch = 'R';
+                                                       }
+                                                       else {
+                                                               if (flags & INMEMORY)
+                                                                       ch = 'm';
+                                                               else
+                                                                       ch = 'r';
+                                                       }
+                                                       printf("%c%03d(", ch, regoff);
+                                                       show_allocation(i, flags, regoff);
+                                                       printf(") ");
+                                               }
+                                               else {
+                                                       if (flags & SAVEDVAR)
+                                                               printf("  I       ");
+                                                       else
+                                                               printf("  i       ");
+                                               }
+                                       }
+                               }
+                               printf("\n");
+                       }
+                       printf("\n");
+               }
+       }
+
+       if (rd->memuse && irstage >= SHOW_REGS) {
+               int max;
+
+               max = rd->memuse;
+               printf("Stack slots: (memuse=%d", rd->memuse);
+               if (irstage >= SHOW_CODE) {
+                       printf(", stackframesize=%d", cd->stackframesize);
+                       max = cd->stackframesize;
+               }
+               printf(")\n");
+               for (i = 0; i < max; ++i) {
+                       printf("    M%02d = 0x%02x(sp): ", i, i * 8);
+                       for (j = 0; j < jd->vartop; ++j) {
+                               varinfo *v = VAR(j);
+                               if ((v->flags & INMEMORY) && (v->vv.regoff == i)) {
+                                       show_variable(jd, j, irstage);
+                                       putchar(' ');
+                               }
+                       }
+
+                       printf("\n");
+
+               }
+               printf("\n");
+       }
+
+#if defined(ENABLE_REPLACEMENT)
+       if (code->rplpoints) {
+               printf("Replacement Points:\n");
+               replace_show_replacement_points(code);
+               printf("\n");
+       }
+#endif /* defined(ENABLE_REPLACEMENT) */
+
+#if defined(ENABLE_DISASSEMBLER)
+       /* show code before first basic block */
+
+       if ((stage >= SHOW_CODE) && JITDATA_HAS_FLAG_SHOWDISASSEMBLE(jd)) {
+               pc = (u1 *) ((ptrint) code->mcode + cd->dseglen);
+
+               for (; pc < (u1 *) ((ptrint) code->mcode + cd->dseglen + jd->basicblocks[0].mpc);)
+                       DISASSINSTR(pc);
+
+               printf("\n");
+       }
+#endif
+
+       /* show code of all basic blocks */
+
+       for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next)
+               show_basicblock(jd, bptr, stage);
+
+#if 0 && defined(ENABLE_DISASSEMBLER)
+       /* show code after last basic block */
+
+       if (stage >= SHOW_CODE && opt_showdisassemble) {
+               printf("\nStubs code:\n");
+               printf("Length: %d\n\n", (s4) (code->mcodelength -
+                                                                          ((ptrint) cd->dseglen + lastbptr->mpc)));
+
+               pc = (u1 *) ((ptrint) code->mcode + cd->dseglen + lastbptr->mpc);
+
+               for (; (ptrint) pc < ((ptrint) code->mcode + code->mcodelength);)
+                       DISASSINSTR(pc);
+
+               printf("\n");
+       }
+#endif
+
+       mutex.unlock();
+
+       /* finally flush the output */
+
+       fflush(stdout);
+}
+#endif /* !defined(NDEBUG) */
+
+
+#if !defined(NDEBUG) && defined(ENABLE_INLINING)
+static void show_inline_info(jitdata *jd, insinfo_inline *ii, s4 opcode, s4 stage)
+{
+       s4 *jl;
+       s4 n;
+
+       printf("(pt %d+%d+%d st ", 
+                       ii->throughcount - (ii->stackvarscount - ii->paramcount),
+                       ii->stackvarscount - ii->paramcount,
+                       ii->paramcount);
+       show_variable_array(jd, ii->stackvars, ii->stackvarscount, stage);
+
+       if (opcode == ICMD_INLINE_START || opcode == ICMD_INLINE_END) {
+               printf(" jl ");
+               jl = (opcode == ICMD_INLINE_START) ? ii->javalocals_start : ii->javalocals_end;
+               n = (opcode == ICMD_INLINE_START) ? ii->method->maxlocals : ii->outer->maxlocals;
+               show_javalocals_array(jd, jl, n, stage);
+       }
+
+       printf(") ");
+
+#if 0
+       printf("(");
+       method_print(ii->outer);
+       printf(" ==> ");
+#endif
+
+       method_print(ii->method);
+}
+#endif /* !defined(NDEBUG) && defined(ENABLE_INLINING) */
+
+
+/* show_basicblock *************************************************************
+
+   Print the intermediate representation of a basic block.
+
+   NOTE: Currently this function may only be called after register allocation!
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void show_basicblock(jitdata *jd, basicblock *bptr, int stage)
+{
+       codeinfo    *code;
+       codegendata *cd;
+       s4           i;
+       bool         deadcode;
+       instruction *iptr;
+       int          irstage;
+#if defined(ENABLE_DISASSEMBLER)
+       methodinfo  *m;                     /* this is only a dummy               */
+       void        *pc;
+       s4           linenumber;
+       s4           currentlinenumber;
+#endif
+
+       /* get required compiler data */
+
+       code = jd->code;
+       cd   = jd->cd;
+
+       if (bptr->flags != BBDELETED) {
+#if defined(ENABLE_INTRP)
+               if (opt_intrp) {
+                       deadcode = false;
+                       irstage = SHOW_PARSE;
+               }
+               else
+#endif
+               {
+                       deadcode = (bptr->flags < BBREACHED);
+                       irstage = stage;
+               }
+
+               printf("======== %sL%03d ======== %s(flags: %d, bitflags: %01x, next: %d, type: ",
+#if defined(ENABLE_REPLACEMENT)
+                               (bptr->bitflags & BBFLAG_REPLACEMENT) ? "<REPLACE> " : 
+#endif
+                                                                                                               "",
+                          bptr->nr, 
+                          (deadcode && stage >= SHOW_STACK) ? "DEADCODE! " : "",
+                          bptr->flags, bptr->bitflags, 
+                          (bptr->next) ? (bptr->next->nr) : -1);
+
+               switch (bptr->type) {
+               case BBTYPE_STD:
+                       printf("STD");
+                       break;
+               case BBTYPE_EXH:
+                       printf("EXH");
+                       break;
+               case BBTYPE_SBR:
+                       printf("SBR");
+                       break;
+               }
+
+               printf(", icount: %d", bptr->icount);
+
+               if (irstage >= SHOW_CFG) {
+                       printf(", preds: %d [ ", bptr->predecessorcount);
+
+                       for (i = 0; i < bptr->predecessorcount; i++)
+                               printf("%d ", bptr->predecessors[i]->nr);
+
+                       printf("]");
+               }
+
+               printf("):");
+
+               if (bptr->original)
+                       printf(" (clone of L%03d)", bptr->original->nr);
+               else {
+                       basicblock *b = bptr->copied_to;
+                       if (b) {
+                               printf(" (copied to ");
+                               for (; b; b = b->copied_to)
+                                       printf("L%03d ", b->nr);
+                               printf(")");
+                       }
+               }
+
+               printf("\n");
+
+               if (irstage >= SHOW_CFG) {
+                       printf("succs: %d [ ", bptr->successorcount);
+
+                       for (i = 0; i < bptr->successorcount; i++)
+                               printf("%d ", bptr->successors[i]->nr);
+
+                       printf("]\n");
+               }
+
+               if (irstage >= SHOW_STACK) {
+                       printf("IN:  ");
+                       show_variable_array(jd, bptr->invars, bptr->indepth, irstage);
+                       printf(" javalocals: ");
+                       if (bptr->javalocals)
+                               show_javalocals_array(jd, bptr->javalocals, bptr->method->maxlocals, irstage);
+                       else
+                               printf("null");
+                       printf("\n");
+               }
+
+#if defined(ENABLE_INLINING)
+               if (bptr->inlineinfo) {
+                       printf("inlineinfo: ");
+                       show_inline_info(jd, bptr->inlineinfo, -1, irstage);
+                       printf("\n");
+               }
+#endif /* defined(ENABLE_INLINING) */
+
+#if defined(ENABLE_SSA)
+       
+               iptr = bptr->phis;
+
+               for (i = 0; i < bptr->phicount; i++, iptr++) {
+                       printf("%4d:%4d:  ", iptr->line, iptr->flags.bits >> INS_FLAG_ID_SHIFT);
+
+                       show_icmd(jd, iptr, deadcode, irstage);
+                       printf("\n");
+               }
+#endif
+
+               iptr = bptr->iinstr;
+
+               for (i = 0; i < bptr->icount; i++, iptr++) {
+                       printf("%4d:%4d:  ", iptr->line, iptr->flags.bits >> INS_FLAG_ID_SHIFT);
+
+                       show_icmd(jd, iptr, deadcode, irstage);
+                       printf("\n");
+               }
+
+               if (irstage >= SHOW_STACK) {
+                       printf("OUT: ");
+                       show_variable_array(jd, bptr->outvars, bptr->outdepth, irstage);
+                       printf("\n");
+               }
+
+#if defined(ENABLE_DISASSEMBLER)
+               if ((stage >= SHOW_CODE) && JITDATA_HAS_FLAG_SHOWDISASSEMBLE(jd) &&
+                       (!deadcode)) 
+               {
+                       printf("\n");
+                       pc         = (void *) (code->mcode + cd->dseglen + bptr->mpc);
+                       linenumber = 0;
+
+                       if (bptr->next != NULL) {
+                               for (; pc < (void *) (code->mcode + cd->dseglen + bptr->next->mpc);) {
+                                       currentlinenumber = code->linenumbertable->find(&m, pc);
+
+                                       if (currentlinenumber != linenumber) {
+                                               linenumber = currentlinenumber;
+                                               printf("%4d:\n", linenumber);
+                                       }
+
+                                       DISASSINSTR(pc);
+                               }
+                       }
+                       else {
+                               for (; pc < (void *) (code->mcode + code->mcodelength);) {
+                                       currentlinenumber = code->linenumbertable->find(&m, pc);
+
+                                       if (currentlinenumber != linenumber) {
+                                               linenumber = currentlinenumber;
+                                               printf("%4d:\n", linenumber);
+                                       }
+
+                                       DISASSINSTR(pc);
+                               }
+                       }
+                       printf("\n");
+               }
+#endif
+       }
+}
+#endif /* !defined(NDEBUG) */
+
+
+/* show_icmd *******************************************************************
+
+   Print the intermediate representation of an instruction.
+
+   NOTE: Currently this function may only be called after register allocation!
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+
+#define SHOW_TARGET(target)                                          \
+        if (stage >= SHOW_PARSE) {                                   \
+            printf("--> L%03d ", (target).block->nr);                \
+        }                                                            \
+        else {                                                       \
+            printf("--> insindex %d ", (target).insindex);           \
+        }
+
+#define SHOW_INT_CONST(val)                                          \
+        if (stage >= SHOW_PARSE) {                                   \
+            printf("%d (0x%08x) ", (int32_t) (val), (int32_t) (val)); \
+        }                                                            \
+        else {                                                       \
+            printf("iconst ");                                       \
+        }
+
+#if SIZEOF_VOID_P == 4
+#define SHOW_LNG_CONST(val)                                          \
+        if (stage >= SHOW_PARSE)                                     \
+            printf("%lld (0x%016llx) ", (val), (val));               \
+        else                                                         \
+            printf("lconst ");
+#else
+#define SHOW_LNG_CONST(val)                                          \
+        if (stage >= SHOW_PARSE)                                     \
+            printf("%ld (0x%016lx) ", (val), (val));                 \
+        else                                                         \
+            printf("lconst ");
+#endif
+
+#if SIZEOF_VOID_P == 4
+#define SHOW_ADR_CONST(val)                                          \
+        if (stage >= SHOW_PARSE)                                     \
+            printf("0x%08x ", (ptrint) (val));                       \
+        else                                                         \
+            printf("aconst ");
+#else
+#define SHOW_ADR_CONST(val)                                          \
+        if (stage >= SHOW_PARSE)                                     \
+            printf("0x%016lx ", (ptrint) (val));                     \
+        else                                                         \
+            printf("aconst ");
+#endif
+
+#define SHOW_FLT_CONST(val)                                          \
+        if (stage >= SHOW_PARSE) {                                   \
+            imm_union v;                                             \
+            v.f = (val);                                             \
+            printf("%g (0x%08x) ", (val), v.i);                      \
+        }                                                            \
+        else {                                                       \
+            printf("fconst ");                                       \
+        }
+
+#if SIZEOF_VOID_P == 4
+#define SHOW_DBL_CONST(val)                                          \
+        if (stage >= SHOW_PARSE) {                                   \
+            imm_union v;                                             \
+            v.d = (val);                                             \
+            printf("%g (0x%016llx) ", (val), v.l);                   \
+        }                                                            \
+        else                                                         \
+            printf("dconst ");
+#else
+#define SHOW_DBL_CONST(val)                                          \
+        if (stage >= SHOW_PARSE) {                                   \
+            imm_union v;                                             \
+            v.d = (val);                                             \
+            printf("%g (0x%016lx) ", (val), v.l);                    \
+        }                                                            \
+        else                                                         \
+            printf("dconst ");
+#endif
+
+#define SHOW_INDEX(index)                                            \
+        if (stage >= SHOW_PARSE) {                                   \
+            printf("%d ", index);                                    \
+        }                                                            \
+        else {                                                       \
+            printf("index");                                         \
+        }
+
+#define SHOW_STRING(val)                                             \
+        if (stage >= SHOW_PARSE) {                                   \
+            putchar('"');                                            \
+            utf_display_printable_ascii(                             \
+               javastring_toutf((java_handle_t *)(val), false));     \
+            printf("\" ");                                           \
+        }                                                            \
+        else {                                                       \
+            printf("string ");                                       \
+        }
+
+#define SHOW_CLASSREF_OR_CLASSINFO(c)                                \
+        if (stage >= SHOW_PARSE) {                                   \
+            if (IS_CLASSREF(c))                                      \
+                class_classref_print(c.ref);                         \
+            else                                                     \
+                class_print(c.cls);                                  \
+            putchar(' ');                                            \
+        }                                                            \
+        else {                                                       \
+            printf("class ");                                        \
+        }
+
+#define SHOW_FIELD(fmiref)                                           \
+        if (stage >= SHOW_PARSE) {                                   \
+            field_fieldref_print(fmiref);                            \
+            putchar(' ');                                            \
+        }                                                            \
+        else {                                                       \
+            printf("field ");                                        \
+        }
+
+#define SHOW_VARIABLE(v)                                             \
+    show_variable(jd, (v), stage)
+
+#define SHOW_S1(iptr)                                                \
+        if (stage >= SHOW_STACK) {                                   \
+            SHOW_VARIABLE(iptr->s1.varindex);                        \
+        }
+
+#define SHOW_S2(iptr)                                                \
+        if (stage >= SHOW_STACK) {                                   \
+            SHOW_VARIABLE(iptr->sx.s23.s2.varindex);                 \
+        }
+
+#define SHOW_S3(iptr)                                                \
+    if (stage >= SHOW_STACK) {                                       \
+        SHOW_VARIABLE(iptr->sx.s23.s3.varindex);                     \
+    }
+
+#define SHOW_DST(iptr)                                               \
+    if (stage >= SHOW_STACK) {                                       \
+        printf("=> ");                                               \
+        SHOW_VARIABLE(iptr->dst.varindex);                           \
+    }
+
+#define SHOW_S1_LOCAL(iptr)                                          \
+    if (stage >= SHOW_STACK) {                                       \
+        printf("L%d ", iptr->s1.varindex);                           \
+    }                                                                \
+    else {                                                           \
+        printf("JavaL%d ", iptr->s1.varindex);                       \
+    }
+
+#define SHOW_DST_LOCAL(iptr)                                         \
+    if (stage >= SHOW_STACK) {                                       \
+        printf("=> L%d ", iptr->dst.varindex);                       \
+    }                                                                \
+    else {                                                           \
+        printf("=> JavaL%d ", iptr->dst.varindex);                   \
+    }
+
+void show_allocation(s4 type, s4 flags, s4 regoff)
+{
+       if (type == TYPE_RET) {
+               printf("N/A");
+               return;
+       }
+
+       if (flags & INMEMORY) {
+               printf("M%02d", regoff);
+               return;
+       }
+
+#ifdef HAS_ADDRESS_REGISTER_FILE
+       if (type == TYPE_ADR) {
+               printf("R%02d", regoff);
+               return;
+       }
+#endif
+
+       if (IS_FLT_DBL_TYPE(type)) {
+               printf("F%02d", regoff);
+               return;
+       }
+
+#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
+       if (IS_2_WORD_TYPE(type)) {
+# if defined(ENABLE_JIT) && defined(ENABLE_DISASSEMBLER)
+#  if defined(ENABLE_INTRP)
+               if (opt_intrp)
+                       printf("%3d/%3d", GET_LOW_REG(regoff),
+                                       GET_HIGH_REG(regoff));
+               else
+#  endif
+                       printf("%3s/%3s", abi_registers_integer_name[GET_LOW_REG(regoff)],
+                                  abi_registers_integer_name[GET_HIGH_REG(regoff)]);
+# else
+               printf("%3d/%3d", GET_LOW_REG(regoff),
+                          GET_HIGH_REG(regoff));
+# endif
+               return;
+       } 
+#endif /* defined(SUPPORT_COMBINE_INTEGER_REGISTERS) */
+
+#if defined(ENABLE_JIT) && defined(ENABLE_DISASSEMBLER)
+# if defined(ENABLE_INTRP)
+       if (opt_intrp)
+               printf("%3d", regoff);
+       else
+# endif
+               printf("%3s", abi_registers_integer_name[regoff]);
+#else
+       printf("%3d", regoff);
+#endif
+}
+
+void show_variable(jitdata *jd, s4 index, int stage)
+{
+       show_variable_intern(jd, index, stage);
+       putchar(' ');
+}
+
+static void show_variable_intern(jitdata *jd, s4 index, int stage)
+{
+       char type;
+       char kind;
+       varinfo *v;
+
+       if (index < 0 || index >= jd->vartop) {
+               printf("<INVALID INDEX:%d>", index);
+               return;
+       }
+
+       v = VAR(index);
+
+       switch (v->type) {
+               case TYPE_INT: type = 'i'; break;
+               case TYPE_LNG: type = 'l'; break;
+               case TYPE_FLT: type = 'f'; break;
+               case TYPE_DBL: type = 'd'; break;
+               case TYPE_ADR: type = 'a'; break;
+               case TYPE_RET: type = 'r'; break;
+               default:       type = '?';
+       }
+
+       if (index < jd->localcount) {
+               kind = 'L';
+               if (v->flags & (PREALLOC | INOUT))
+                               printf("<INVALID FLAGS!>");
+       }
+       else {
+               if (v->flags & PREALLOC) {
+                       kind = 'A';
+                       if (v->flags & INOUT) {
+                               /* PREALLOC is used to avoid allocation of TYPE_RET */
+                               if (v->type == TYPE_RET)
+                                       kind = 'i';
+                               else
+                                       printf("<INVALID FLAGS!>");
+                       }
+               }
+               else if (v->flags & INOUT)
+                       kind = 'I';
+               else
+                       kind = 'T';
+       }
+
+       printf("%c%c%d", kind, type, index);
+
+       if (v->flags & SAVEDVAR)
+               putchar('!');
+
+       if (stage >= SHOW_REGS || (v->flags & PREALLOC)) {
+               putchar('(');
+               show_allocation(v->type, v->flags, v->vv.regoff);
+               putchar(')');
+       }
+
+       if (v->type == TYPE_RET && (v->flags & PREALLOC)) {
+               printf("(L%03d)", v->vv.retaddr->nr);
+       }
+}
+
+static void show_variable_array_intern(jitdata *jd, s4 *vars, int n, int stage,
+                                                                          bool javalocals)
+{
+       int i;
+       int nr;
+
+       if (vars == NULL) {
+               printf("<null>");
+               return;
+       }
+
+       printf("[");
+       for (i=0; i<n; ++i) {
+               if (i)
+                       putchar(' ');
+               if (vars[i] < 0) {
+                       if (vars[i] == UNUSED)
+                               putchar('-');
+                       else if (javalocals) {
+                               nr = RETADDR_FROM_JAVALOCAL(vars[i]);
+                               printf("ret(L%03d)", nr);
+                       }
+                       else {
+                               printf("<INVALID INDEX:%d>", vars[i]);
+                       }
+               }
+               else
+                       show_variable_intern(jd, vars[i], stage);
+       }
+       printf("]");
+}
+
+void show_variable_array(jitdata *jd, s4 *vars, int n, int stage)
+{
+       show_variable_array_intern(jd, vars, n, stage, false);
+}
+
+void show_javalocals_array(jitdata *jd, s4 *vars, int n, int stage)
+{
+       show_variable_array_intern(jd, vars, n, stage, true);
+}
+
+void show_icmd(jitdata *jd, instruction *iptr, bool deadcode, int stage)
+{
+       u2                 opcode;
+       branch_target_t   *table;
+       lookup_target_t   *lookup;
+       constant_FMIref   *fmiref;
+       s4                *argp;
+       s4                 i;
+
+       /* get the opcode and the condition */
+
+       opcode    =  iptr->opc;
+
+       printf("%s ", icmd_table[opcode].name);
+
+       if (stage < SHOW_PARSE)
+               return;
+
+       if (deadcode)
+               stage = SHOW_PARSE;
+
+       /* Print the condition for conditional instructions. */
+
+       /* XXX print condition from flags */
+
+       if (iptr->flags.bits & INS_FLAG_UNRESOLVED)
+               printf("(UNRESOLVED) ");
+
+       switch (opcode) {
+
+       case ICMD_POP:
+       case ICMD_CHECKNULL:
+               SHOW_S1(iptr);
+               break;
+
+               /* unary */
+       case ICMD_ARRAYLENGTH:
+       case ICMD_INEG:
+       case ICMD_LNEG:
+       case ICMD_FNEG:
+       case ICMD_DNEG:
+       case ICMD_I2L:
+       case ICMD_I2F:
+       case ICMD_I2D:
+       case ICMD_L2I:
+       case ICMD_L2F:
+       case ICMD_L2D:
+       case ICMD_F2I:
+       case ICMD_F2L:
+       case ICMD_F2D:
+       case ICMD_D2I:
+       case ICMD_D2L:
+       case ICMD_D2F:
+       case ICMD_INT2BYTE:
+       case ICMD_INT2CHAR:
+       case ICMD_INT2SHORT:
+               SHOW_S1(iptr);
+               SHOW_DST(iptr);
+               break;
+
+               /* binary */
+       case ICMD_IADD:
+       case ICMD_LADD:
+       case ICMD_FADD:
+       case ICMD_DADD:
+       case ICMD_ISUB:
+       case ICMD_LSUB:
+       case ICMD_FSUB:
+       case ICMD_DSUB:
+       case ICMD_IMUL:
+       case ICMD_LMUL:
+       case ICMD_FMUL:
+       case ICMD_DMUL:
+       case ICMD_IDIV:
+       case ICMD_LDIV:
+       case ICMD_FDIV:
+       case ICMD_DDIV:
+       case ICMD_IREM:
+       case ICMD_LREM:
+       case ICMD_FREM:
+       case ICMD_DREM:
+       case ICMD_ISHL:
+       case ICMD_LSHL:
+       case ICMD_ISHR:
+       case ICMD_LSHR:
+       case ICMD_IUSHR:
+       case ICMD_LUSHR:
+       case ICMD_IAND:
+       case ICMD_LAND:
+       case ICMD_IOR:
+       case ICMD_LOR:
+       case ICMD_IXOR:
+       case ICMD_LXOR:
+       case ICMD_LCMP:
+       case ICMD_FCMPL:
+       case ICMD_FCMPG:
+       case ICMD_DCMPL:
+       case ICMD_DCMPG:
+               SHOW_S1(iptr);
+               SHOW_S2(iptr);
+               SHOW_DST(iptr);
+               break;
+
+               /* binary/const INT */
+       case ICMD_IADDCONST:
+       case ICMD_ISUBCONST:
+       case ICMD_IMULCONST:
+       case ICMD_IMULPOW2:
+       case ICMD_IDIVPOW2:
+       case ICMD_IREMPOW2:
+       case ICMD_IANDCONST:
+       case ICMD_IORCONST:
+       case ICMD_IXORCONST:
+       case ICMD_ISHLCONST:
+       case ICMD_ISHRCONST:
+       case ICMD_IUSHRCONST:
+       case ICMD_LSHLCONST:
+       case ICMD_LSHRCONST:
+       case ICMD_LUSHRCONST:
+               SHOW_S1(iptr);
+               SHOW_INT_CONST(iptr->sx.val.i); 
+               SHOW_DST(iptr);
+               break;
+
+               /* ?ASTORECONST (trinary/const INT) */
+       case ICMD_IASTORECONST:
+       case ICMD_BASTORECONST:
+       case ICMD_CASTORECONST:
+       case ICMD_SASTORECONST:
+               SHOW_S1(iptr);
+               SHOW_S2(iptr);
+               SHOW_INT_CONST(iptr->sx.s23.s3.constval);
+               break;
+
+               /* const INT */
+       case ICMD_ICONST:
+               SHOW_INT_CONST(iptr->sx.val.i); 
+               SHOW_DST(iptr);
+               break;
+
+               /* binary/const LNG */
+       case ICMD_LADDCONST:
+       case ICMD_LSUBCONST:
+       case ICMD_LMULCONST:
+       case ICMD_LMULPOW2:
+       case ICMD_LDIVPOW2:
+       case ICMD_LREMPOW2:
+       case ICMD_LANDCONST:
+       case ICMD_LORCONST:
+       case ICMD_LXORCONST:
+               SHOW_S1(iptr);
+               SHOW_LNG_CONST(iptr->sx.val.l);
+               SHOW_DST(iptr);
+               break;
+
+               /* trinary/const LNG (<= pointer size) */
+       case ICMD_LASTORECONST:
+               SHOW_S1(iptr);
+               SHOW_S2(iptr);
+               SHOW_ADR_CONST(iptr->sx.s23.s3.constval);
+               break;
+
+               /* const LNG */
+       case ICMD_LCONST:
+               SHOW_LNG_CONST(iptr->sx.val.l); 
+               SHOW_DST(iptr);
+               break;
+
+               /* const FLT */
+       case ICMD_FCONST:
+               SHOW_FLT_CONST(iptr->sx.val.f); 
+               SHOW_DST(iptr);
+               break;
+
+               /* const DBL */
+       case ICMD_DCONST:
+               SHOW_DBL_CONST(iptr->sx.val.d); 
+               SHOW_DST(iptr);
+               break;
+
+               /* const ADR */
+       case ICMD_ACONST:
+               if (iptr->flags.bits & INS_FLAG_CLASS) {
+                       SHOW_ADR_CONST(iptr->sx.val.anyptr);
+                       SHOW_CLASSREF_OR_CLASSINFO(iptr->sx.val.c);
+               }
+               else if (iptr->sx.val.anyptr == NULL) {
+                       printf("NULL ");
+               }
+               else {
+                       SHOW_ADR_CONST(iptr->sx.val.anyptr);
+                       SHOW_STRING(iptr->sx.val.stringconst);
+               }
+               SHOW_DST(iptr);
+               break;
+
+       case ICMD_AASTORECONST:
+               SHOW_S1(iptr);
+               SHOW_S2(iptr);
+               printf("%p ", (void*) iptr->sx.s23.s3.constval);
+               break;
+
+       case ICMD_GETFIELD:        /* 1 -> 1 */
+       case ICMD_PUTFIELD:        /* 2 -> 0 */
+       case ICMD_PUTSTATIC:       /* 1 -> 0 */
+       case ICMD_GETSTATIC:       /* 0 -> 1 */
+       case ICMD_PUTSTATICCONST:  /* 0 -> 0 */
+       case ICMD_PUTFIELDCONST:   /* 1 -> 0 */
+               if (opcode != ICMD_GETSTATIC && opcode != ICMD_PUTSTATICCONST) {
+                       SHOW_S1(iptr);
+                       if (opcode == ICMD_PUTFIELD) {
+                               SHOW_S2(iptr);
+                       }
+               }
+               INSTRUCTION_GET_FIELDREF(iptr, fmiref);
+               SHOW_FIELD(fmiref);
+
+               if (opcode == ICMD_GETSTATIC || opcode == ICMD_GETFIELD) {
+                       SHOW_DST(iptr);
+               }
+               break;
+
+       case ICMD_IINC:
+               SHOW_S1_LOCAL(iptr);
+               SHOW_INT_CONST(iptr->sx.val.i);
+               SHOW_DST_LOCAL(iptr);
+               break;
+
+       case ICMD_IASTORE:
+       case ICMD_SASTORE:
+       case ICMD_BASTORE:
+       case ICMD_CASTORE:
+       case ICMD_LASTORE:
+       case ICMD_DASTORE:
+       case ICMD_FASTORE:
+       case ICMD_AASTORE:
+               SHOW_S1(iptr);
+               SHOW_S2(iptr);
+               SHOW_S3(iptr);
+               break;
+
+       case ICMD_IALOAD:
+       case ICMD_SALOAD:
+       case ICMD_BALOAD:
+       case ICMD_CALOAD:
+       case ICMD_LALOAD:
+       case ICMD_DALOAD:
+       case ICMD_FALOAD:
+       case ICMD_AALOAD:
+               SHOW_S1(iptr);
+               SHOW_S2(iptr);
+               SHOW_DST(iptr);
+               break;
+
+       case ICMD_RET:
+               SHOW_S1_LOCAL(iptr);
+               if (stage >= SHOW_STACK) {
+                       printf(" ---> L%03d", iptr->dst.block->nr);
+               }
+               break;
+
+       case ICMD_ILOAD:
+       case ICMD_LLOAD:
+       case ICMD_FLOAD:
+       case ICMD_DLOAD:
+       case ICMD_ALOAD:
+               SHOW_S1_LOCAL(iptr);
+               SHOW_DST(iptr);
+               break;
+
+       case ICMD_ISTORE:
+       case ICMD_LSTORE:
+       case ICMD_FSTORE:
+       case ICMD_DSTORE:
+       case ICMD_ASTORE:
+               SHOW_S1(iptr);
+               SHOW_DST_LOCAL(iptr);
+               if (stage >= SHOW_STACK && iptr->sx.s23.s3.javaindex != UNUSED)
+                       printf(" (javaindex %d)", iptr->sx.s23.s3.javaindex);
+               if (iptr->flags.bits & INS_FLAG_RETADDR) {
+                       printf(" (retaddr L%03d)", RETADDR_FROM_JAVALOCAL(iptr->sx.s23.s2.retaddrnr));
+               }
+               break;
+
+       case ICMD_NEW:
+               SHOW_DST(iptr);
+               break;
+
+       case ICMD_NEWARRAY:
+               SHOW_DST(iptr);
+               break;
+
+       case ICMD_ANEWARRAY:
+               SHOW_DST(iptr);
+               break;
+
+       case ICMD_MULTIANEWARRAY:
+               if (stage >= SHOW_STACK) {
+                       argp = iptr->sx.s23.s2.args;
+                       i = iptr->s1.argcount;
+                       while (i--) {
+                               SHOW_VARIABLE(*(argp++));
+                       }
+               }
+               else {
+                       printf("argcount=%d ", iptr->s1.argcount);
+               }
+               class_classref_or_classinfo_print(iptr->sx.s23.s3.c);
+               putchar(' ');
+               SHOW_DST(iptr);
+               break;
+
+       case ICMD_CHECKCAST:
+               SHOW_S1(iptr);
+               class_classref_or_classinfo_print(iptr->sx.s23.s3.c);
+               putchar(' ');
+               SHOW_DST(iptr);
+               break;
+
+       case ICMD_INSTANCEOF:
+               SHOW_S1(iptr);
+               SHOW_DST(iptr);
+               break;
+
+       case ICMD_INLINE_START:
+       case ICMD_INLINE_END:
+       case ICMD_INLINE_BODY:
+#if defined(ENABLE_INLINING)
+               {
+                       insinfo_inline *ii = iptr->sx.s23.s3.inlineinfo;
+                       show_inline_info(jd, ii, opcode, stage);
+               }
+#endif
+               break;
+
+       case ICMD_BUILTIN:
+               if (stage >= SHOW_STACK) {
+                       argp = iptr->sx.s23.s2.args;
+                       i = iptr->s1.argcount;
+                       while (i--) {
+                               if ((iptr->s1.argcount - 1 - i) == iptr->sx.s23.s3.bte->md->paramcount)
+                                       printf(" pass-through: ");
+                               SHOW_VARIABLE(*(argp++));
+                       }
+               }
+               printf("%s ", iptr->sx.s23.s3.bte->cname);
+               if (iptr->sx.s23.s3.bte->md->returntype.type != TYPE_VOID) {
+                       SHOW_DST(iptr);
+               }
+               break;
+
+       case ICMD_INVOKEVIRTUAL:
+       case ICMD_INVOKESPECIAL:
+       case ICMD_INVOKESTATIC:
+       case ICMD_INVOKEINTERFACE:
+               if (stage >= SHOW_STACK) {
+                       methoddesc *md;
+                       INSTRUCTION_GET_METHODDESC(iptr, md);
+                       argp = iptr->sx.s23.s2.args;
+                       i = iptr->s1.argcount;
+                       while (i--) {
+                               if ((iptr->s1.argcount - 1 - i) == md->paramcount)
+                                       printf(" pass-through: ");
+                               SHOW_VARIABLE(*(argp++));
+                       }
+               }
+               INSTRUCTION_GET_METHODREF(iptr, fmiref);
+               method_methodref_print(fmiref);
+               if (fmiref->parseddesc.md->returntype.type != TYPE_VOID) {
+                       putchar(' ');
+                       SHOW_DST(iptr);
+               }
+               break;
+
+       case ICMD_IFEQ:
+       case ICMD_IFNE:
+       case ICMD_IFLT:
+       case ICMD_IFGE:
+       case ICMD_IFGT:
+       case ICMD_IFLE:
+               SHOW_S1(iptr);
+               SHOW_INT_CONST(iptr->sx.val.i); 
+               SHOW_TARGET(iptr->dst);
+               break;
+
+       case ICMD_IF_LEQ:
+       case ICMD_IF_LNE:
+       case ICMD_IF_LLT:
+       case ICMD_IF_LGE:
+       case ICMD_IF_LGT:
+       case ICMD_IF_LLE:
+               SHOW_S1(iptr);
+               SHOW_LNG_CONST(iptr->sx.val.l); 
+               SHOW_TARGET(iptr->dst);
+               break;
+
+       case ICMD_GOTO:
+               SHOW_TARGET(iptr->dst);
+               break;
+
+       case ICMD_JSR:
+               SHOW_TARGET(iptr->sx.s23.s3.jsrtarget);
+               SHOW_DST(iptr);
+               break;
+
+       case ICMD_IFNULL:
+       case ICMD_IFNONNULL:
+               SHOW_S1(iptr);
+               SHOW_TARGET(iptr->dst);
+               break;
+
+       case ICMD_IF_ICMPEQ:
+       case ICMD_IF_ICMPNE:
+       case ICMD_IF_ICMPLT:
+       case ICMD_IF_ICMPGE:
+       case ICMD_IF_ICMPGT:
+       case ICMD_IF_ICMPLE:
+
+       case ICMD_IF_LCMPEQ:
+       case ICMD_IF_LCMPNE:
+       case ICMD_IF_LCMPLT:
+       case ICMD_IF_LCMPGE:
+       case ICMD_IF_LCMPGT:
+       case ICMD_IF_LCMPLE:
+
+       case ICMD_IF_ACMPEQ:
+       case ICMD_IF_ACMPNE:
+               SHOW_S1(iptr);
+               SHOW_S2(iptr);
+               SHOW_TARGET(iptr->dst);
+               break;
+
+       case ICMD_TABLESWITCH:
+               SHOW_S1(iptr);
+               table = iptr->dst.table;
+
+               i = iptr->sx.s23.s3.tablehigh - iptr->sx.s23.s2.tablelow + 1;
+
+               printf("high=%d low=%d count=%d\n", iptr->sx.s23.s3.tablehigh, iptr->sx.s23.s2.tablelow, i);
+               while (--i >= 0) {
+                       printf("\t\t%d --> ", (int) (table - iptr->dst.table));
+                       printf("L%03d\n", table->block->nr);
+                       table++;
+               }
+
+               break;
+
+       case ICMD_LOOKUPSWITCH:
+               SHOW_S1(iptr);
+
+               printf("count=%d, default=L%03d\n",
+                          iptr->sx.s23.s2.lookupcount,
+                          iptr->sx.s23.s3.lookupdefault.block->nr);
+
+               lookup = iptr->dst.lookup;
+               i = iptr->sx.s23.s2.lookupcount;
+
+               while (--i >= 0) {
+                       printf("\t\t%d --> L%03d\n",
+                                  lookup->value,
+                                  lookup->target.block->nr);
+                       lookup++;
+               }
+               break;
+
+       case ICMD_FRETURN:
+       case ICMD_IRETURN:
+       case ICMD_DRETURN:
+       case ICMD_LRETURN:
+               SHOW_S1(iptr);
+               break;
+
+       case ICMD_ARETURN:
+       case ICMD_ATHROW:
+               SHOW_S1(iptr);
+               if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                       /* XXX this needs more work */
+#if 0
+                       unresolved_class_debug_dump(iptr->sx.s23.s2.uc, stdout);
+#endif
+               }
+               break;
+
+       case ICMD_COPY:
+       case ICMD_MOVE:
+               SHOW_S1(iptr);
+               SHOW_DST(iptr);
+               break;
+       case ICMD_GETEXCEPTION:
+               SHOW_DST(iptr);
+               break;
+#if defined(ENABLE_SSA)        
+       case ICMD_PHI:
+               printf("[ ");
+               for (i = 0; i < iptr->s1.argcount; ++i) {
+                       SHOW_VARIABLE(iptr->sx.s23.s2.iargs[i]->dst.varindex);
+               }
+               printf("] ");
+               SHOW_DST(iptr);
+               if (iptr->flags.bits & (1 << 0)) printf("used ");
+               if (iptr->flags.bits & (1 << 1)) printf("redundantAll ");
+               if (iptr->flags.bits & (1 << 2)) printf("redundantOne ");
+               break;
+#endif
+       }
+       fflush(stdout);
+}
+#endif /* !defined(NDEBUG) */
+
+/* Debug output filtering */
+
+#if defined(ENABLE_DEBUG_FILTER)
+
+#if !defined(ENABLE_THREADS)
+u2 _no_threads_filterverbosecallctr[2] = { 0, 0 };
+#endif
+
+struct show_filter {
+       /* Boolean indicating if filter is enabled. */
+       u1 enabled;
+       /* Regular expression the method name is matched against */
+       regex_t regex;
+       /* Flag set on m->filtermatches if regex matches */
+       u1 flag;
+};
+
+typedef struct show_filter show_filter_t;
+
+#define SHOW_FILTERS_SIZE 3
+
+/* Array of filters applyed on a method */
+static struct show_filter show_filters[SHOW_FILTERS_SIZE];
+
+static void show_filter_init(show_filter_t *cf, const char *str, u1 flag, u1 default_flag, const char *description) {
+       int err;
+       char err_buf[128];
+
+       if (str) {
+               err = regcomp(&cf->regex, str, REG_EXTENDED | REG_NOSUB);
+               if (err != 0) {
+                       regerror(err, &cf->regex, err_buf, sizeof(err_buf));
+                       vm_abort(
+                               "Invalid value given for %s: `%s' (%s).", 
+                               description, str, err_buf
+                       );
+               }
+               cf->flag = flag;
+               cf->enabled = 1;
+       } else {
+               cf->flag = default_flag;
+               cf->enabled = 0;
+       }
+}
+
+void show_filters_init(void) {
+
+       show_filter_init(
+               show_filters + 0,
+               opt_filter_verbosecall_include,
+               SHOW_FILTER_FLAG_VERBOSECALL_INCLUDE,
+               SHOW_FILTER_FLAG_VERBOSECALL_INCLUDE,
+               "verbose call include filter"
+       );
+
+       show_filter_init(
+               show_filters + 1,
+               opt_filter_verbosecall_exclude,
+               SHOW_FILTER_FLAG_VERBOSECALL_EXCLUDE,
+               0,
+               "verbose call exclude filter"
+       );
+
+       show_filter_init(
+               show_filters + 2,
+               opt_filter_show_method,
+               SHOW_FILTER_FLAG_SHOW_METHOD,
+               SHOW_FILTER_FLAG_SHOW_METHOD,
+               "show method filter"
+       );
+}
+
+/*
+ (Pseudo)State machine:
+
+ States are INITIAL, INCLUDE1, INCLUDE2, ..., EXCLUDE1, ..., EXCLUDE2, ...
+
+                                                        Enter              Enter
+ Enter                                                  Include            Include
+ Exclude                                                  | |                | |
+  | |    Enter              Enter              Enter      | |     Enter      | |
+  | |    Include            Include            Exclude    | |     Exclude    | |
+  | v   --------->        ---------->        ---------->  | v   ---------->  | v
+INITIAL           INCLUDE1           INCLUDE2           EXCLUDE1           EXCLUDE2
+  | ^   <---------        <----------        <----------  | ^   <----------  | ^
+  | |    Exit               Exit               Exit       | |     Exit       | |
+  | |    Include            Include            Exclude    | |     Exclude    | |
+  | |                                                     | |                | |
+ Exit                                                    Exit               Exit
+ Exclude                                                 Include            Include
+
+  Verbose call scope is active if we are in a INCLUDE state.
+
+  State encoding:
+
+  INITIAL: ctr[0] == 0, ctr[1] == 0
+  INCLUDEN: ctr[1] == N, ctr[1] == 0
+  EXCLUDEN: ctr[1] == N
+*/
+
+void show_filters_apply(methodinfo *m) {
+       int i;
+       int res;
+       char *method_name;
+       s4 len;
+
+       /* compose full name of method */
+
+       len = 
+               utf_bytes(m->clazz->name) +
+               1 +
+               utf_bytes(m->name) +
+               utf_bytes(m->descriptor) +
+               1;
+
+       method_name = MNEW(char, len);
+
+       utf_cat_classname(method_name, m->clazz->name);
+       strcat(method_name, ".");
+       utf_cat(method_name, m->name);
+       utf_cat(method_name, m->descriptor);
+
+       /* reset all flags */
+
+       m->filtermatches = 0;
+
+       for (i = 0; i < SHOW_FILTERS_SIZE; ++i) {
+               if (show_filters[i].enabled) {
+
+                       res = regexec(&show_filters[i].regex, method_name, 0, NULL, 0);
+
+                       if (res == 0) {
+                               m->filtermatches |= show_filters[i].flag;
+                       }
+               } else {
+                       /* Default is to show all */
+                       m->filtermatches |= show_filters[i].flag;
+               }
+       }
+
+       // Release memory.
+       MFREE(method_name, char, len);
+}
+
+#define STATE_IS_INITIAL() ((FILTERVERBOSECALLCTR[0] == 0) && (FILTERVERBOSECALLCTR[1] == 0))
+#define STATE_IS_INCLUDE() ((FILTERVERBOSECALLCTR[0] > 0) && (FILTERVERBOSECALLCTR[1] == 0))
+#define STATE_IS_EXCLUDE() (FILTERVERBOSECALLCTR[1] > 0)
+#define EVENT_INCLUDE() (m->filtermatches & SHOW_FILTER_FLAG_VERBOSECALL_INCLUDE)
+#define EVENT_EXCLUDE() (m->filtermatches & SHOW_FILTER_FLAG_VERBOSECALL_EXCLUDE)
+#define TRANSITION_NEXT_INCLUDE() ++FILTERVERBOSECALLCTR[0]
+#define TRANSITION_PREV_INCLUDE() --FILTERVERBOSECALLCTR[0]
+#define TRANSITION_NEXT_EXCLUDE() ++FILTERVERBOSECALLCTR[1]
+#define TRANSITION_PREV_EXCLUDE() --FILTERVERBOSECALLCTR[1]
+
+#if 0
+void dump_state() {
+       if (STATE_IS_INITIAL()) printf("<INITIAL>\n");
+       else if (STATE_IS_INCLUDE()) printf("<INCLUDE %hd>\n", FILTERVERBOSECALLCTR[0]);
+       else if (STATE_IS_EXCLUDE()) printf("<EXCLUDE %hd>\n", FILTERVERBOSECALLCTR[1]);
+}
+#endif
+
+int show_filters_test_verbosecall_enter(methodinfo *m) {
+
+       int force_show = 0;
+
+       if (STATE_IS_INITIAL()) {
+               if (EVENT_INCLUDE()) {
+                       TRANSITION_NEXT_INCLUDE();
+               }
+       } else if (STATE_IS_INCLUDE()) {
+               if (EVENT_EXCLUDE()) {
+                       TRANSITION_NEXT_EXCLUDE();
+                       /* just entered exclude, show this method */
+                       force_show = 1;
+               } else if (EVENT_INCLUDE()) {
+                       TRANSITION_NEXT_INCLUDE();
+               }
+       } else if (STATE_IS_EXCLUDE()) {
+               if (EVENT_EXCLUDE()) {
+                       TRANSITION_NEXT_EXCLUDE();
+               }
+       }
+
+       return STATE_IS_INCLUDE() || force_show;
+}
+
+int show_filters_test_verbosecall_exit(methodinfo *m) {
+
+       int force_show = 0;
+
+       if (m) {
+               if (STATE_IS_INCLUDE()) {
+                       if (EVENT_INCLUDE()) {
+                               TRANSITION_PREV_INCLUDE();
+                               /* just entered initial, show this method */
+                               if (STATE_IS_INITIAL()) force_show = 1;
+                       }
+           } else if (STATE_IS_EXCLUDE()) {
+                       if (EVENT_EXCLUDE()) {
+                               TRANSITION_PREV_EXCLUDE();
+                       }
+               }
+       }
+
+       return STATE_IS_INCLUDE() || force_show;
+}
+
+#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:
+ */
diff --git a/src/vm/jit/show.h b/src/vm/jit/show.h
deleted file mode 100644 (file)
index 024d223..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-/* src/vm/jit/show.h - showing the intermediate representation
-
-   Copyright (C) 1996-2005, 2006, 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 _SHOW_H
-#define _SHOW_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "config.h"
-#include "vm/types.h"
-
-#include "vm/jit/jit.h"
-
-
-/* compiler stage defines *****************************************************/
-
-#define SHOW_INSTRUCTIONS  0
-#define SHOW_PARSE         1
-#define SHOW_STACK         2
-#define SHOW_CFG           3
-#define SHOW_REGS          4
-#define SHOW_CODE          5
-
-
-/* function prototypes ********************************************************/
-
-#if !defined(NDEBUG)
-extern char *show_jit_type_names[];
-extern char show_jit_type_letters[];
-
-bool show_init(void);
-
-void show_method(jitdata *jd, int stage);
-void show_basicblock(jitdata *jd, basicblock *bptr, int stage);
-void show_icmd(jitdata *jd, instruction *iptr, bool deadcode, int stage);
-void show_variable(jitdata *jd, s4 index, int stage);
-void show_variable_array(jitdata *jd, s4 *vars, int n, int stage);
-void show_javalocals_array(jitdata *jd, s4 *vars, int n, int stage);
-void show_allocation(s4 type, s4 flags, s4 regoff);
-#endif /* !defined(NDEBUG) */
-
-/* Debug output filtering */
-
-#if defined(ENABLE_DEBUG_FILTER)
-void show_filters_init(void);
-#define SHOW_FILTER_FLAG_VERBOSECALL_INCLUDE 0x01
-#define SHOW_FILTER_FLAG_VERBOSECALL_EXCLUDE 0x02
-#define SHOW_FILTER_FLAG_SHOW_METHOD 0x04
-void show_filters_apply(methodinfo *m);
-int show_filters_test_verbosecall_enter(methodinfo *m);
-int show_filters_test_verbosecall_exit(methodinfo *m);
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _SHOW_H */
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
diff --git a/src/vm/jit/show.hpp b/src/vm/jit/show.hpp
new file mode 100644 (file)
index 0000000..1f5852c
--- /dev/null
@@ -0,0 +1,97 @@
+/* src/vm/jit/show.hpp - showing the intermediate representation
+
+   Copyright (C) 1996-2005, 2006, 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 _SHOW_HPP
+#define _SHOW_HPP
+
+#include "config.h"
+#include "vm/types.h"
+
+#include "vm/jit/jit.hpp"
+
+
+/* compiler stage defines *****************************************************/
+
+#define SHOW_INSTRUCTIONS  0
+#define SHOW_PARSE         1
+#define SHOW_STACK         2
+#define SHOW_CFG           3
+#define SHOW_REGS          4
+#define SHOW_CODE          5
+
+
+/* function prototypes ********************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(NDEBUG)
+extern const char *show_jit_type_names[];
+extern const char show_jit_type_letters[];
+
+bool show_init(void);
+
+void show_method(jitdata *jd, int stage);
+void show_basicblock(jitdata *jd, basicblock *bptr, int stage);
+void show_icmd(jitdata *jd, instruction *iptr, bool deadcode, int stage);
+void show_variable(jitdata *jd, s4 index, int stage);
+void show_variable_array(jitdata *jd, s4 *vars, int n, int stage);
+void show_javalocals_array(jitdata *jd, s4 *vars, int n, int stage);
+void show_allocation(s4 type, s4 flags, s4 regoff);
+#endif /* !defined(NDEBUG) */
+
+/* Debug output filtering */
+
+#if defined(ENABLE_DEBUG_FILTER)
+void show_filters_init(void);
+#define SHOW_FILTER_FLAG_VERBOSECALL_INCLUDE 0x01
+#define SHOW_FILTER_FLAG_VERBOSECALL_EXCLUDE 0x02
+#define SHOW_FILTER_FLAG_SHOW_METHOD 0x04
+void show_filters_apply(methodinfo *m);
+int show_filters_test_verbosecall_enter(methodinfo *m);
+int show_filters_test_verbosecall_exit(methodinfo *m);
+#endif
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _SHOW_HPP
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
index b45fe94c47364f004396caf63322ce29902a5a36..2fbeef9f5cd9d5a68b34229e3f6e060387ccc669 100644 (file)
@@ -57,6 +57,7 @@ libarch_la_SOURCES = \
        \
        md-abi.c \
        md-abi.h \
+       md-stubs.hpp \
        md-trap.h \
        md.c \
        md.h
index 93581b3630ca15e43ec3f61ddd33dee93a147dbb..5897ad13ae47b817ad38c5810f821b4902c7d376 100644 (file)
@@ -33,8 +33,6 @@
 
 /* define architecture features ***********************************************/
 
-#define U8_AVAILABLE                     1
-
 #define SUPPORT_DIVISION                 1
 #define SUPPORT_LONG                     1
 
index 6364dbd51fd31266ccee09f31729f5f49620901f..dc0533c2f168d57ad763271470760dc948e16f50 100644 (file)
 
 #include "mm/memory.h"
 
-#include "native/jni.h"
-#include "native/localref.h"
-#include "native/native.h"
+#include "native/localref.hpp"
+#include "native/native.hpp"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/exceptions.hpp"
 #include "vm/global.h"
-#include "vm/loader.h"
+#include "vm/loader.hpp"
 #include "vm/options.h"
 
 #include "vm/jit/abi.h"
 #include "vm/jit/asmpart.h"
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/codegen-common.hpp"
 #include "vm/jit/dseg.h"
-#include "vm/jit/emit-common.h"
-#include "vm/jit/jit.h"
-#include "vm/jit/linenumbertable.h"
+#include "vm/jit/emit-common.hpp"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/linenumbertable.hpp"
 #include "vm/jit/parse.h"
 #include "vm/jit/patcher.h"
 #include "vm/jit/reg.h"
-#include "vm/jit/replace.h"
+#include "vm/jit/replace.hpp"
 #include "vm/jit/stacktrace.hpp"
 
 #include "vm/jit/sparc64/solaris/macro_rename.h"
index ade165128a665165191011b905ce4d3424039e77..b64cf4fc656ed4f6bf991b7ae42fee51ee512caf 100644 (file)
@@ -1,10 +1,8 @@
-/* src/vm/jit/sparc64/codegen.h - code generation macros and definitions for
-                                  Sparc64
+/* src/vm/jit/sparc64/codegen.h - code generation macros and
+                                  definitions for SPARC64
 
-   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.
 
@@ -31,7 +29,7 @@
 #include "config.h"
 #include "vm/types.h"
 
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
 
 #include "md-abi.h" /* for INT_NATARG_CNT */
 
@@ -72,11 +70,6 @@ s4 nat_argintregs[INT_NATARG_CNT];
     } while (0)
 
 
-/* stub defines ***************************************************************/
-
-#define COMPILERSTUB_CODESIZE    4 * 4
-
-
 /* additional functions and macros to generate code ***************************/
 
 
index db4b4ba05f5bb99796fb2ca354f4896f8b909a3d..e7f8f379e6b21bfebf2ecf4a2e1fb8b8d7bcd2dd 100644 (file)
 
 #include "mm/memory.h"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/options.h"
 
 #include "vm/jit/abi.h"
 #include "vm/jit/abi-asm.h"
 #include "vm/jit/asmpart.h"
 #include "vm/jit/dseg.h"
-#include "vm/jit/emit-common.h"
-#include "vm/jit/jit.h"
-#include "vm/jit/replace.h"
+#include "vm/jit/emit-common.hpp"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/replace.hpp"
 
 #include "vm/jit/sparc64/solaris/macro_rename.h"
 
diff --git a/src/vm/jit/sparc64/md-stubs.hpp b/src/vm/jit/sparc64/md-stubs.hpp
new file mode 100644 (file)
index 0000000..eb0dc65
--- /dev/null
@@ -0,0 +1,56 @@
+/* src/vm/jit/sparc64/md-stubs.hpp - SPARC64 JIT stubs
+
+   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 _MD_STUBS_HPP
+#define _MD_STUBS_HPP
+
+#include "config.h"
+
+
+/**
+ * Return the code size of a compiler on a SPARC64 architecture.
+ *
+ * @return Code size in bytes.
+ */
+int CompilerStub::get_code_size()
+{
+       return 4 * 4;
+}
+
+#endif // _MD_STUBS_HPP
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
index ab2b30708acd7ec9b540e205b177e61767d82f33..398fb809d974b3723fd7bce3b92aad02af6d071e 100644 (file)
@@ -33,8 +33,8 @@
 #include "vm/jit/sparc64/md-abi.h"
 
 #include "vm/jit/asmpart.h"
-#include "vm/jit/codegen-common.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/codegen-common.hpp"
+#include "vm/jit/jit.hpp"
 
 
 /* assembler function prototypes **********************************************/
index a66b2552a84a819f7a300a13bd6ff03addca647e..f47f7750d88747e331d0b228e4231be8ffb36ace 100644 (file)
@@ -35,7 +35,7 @@
 
 #include "vm/types.h"
 
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/codegen-common.hpp"
 
 
 /* md_stacktrace_get_returnaddress *********************************************
index ff6e996af6b717558ec14b853ba312fd9532cb95..b8d40910446b085835b2bd9f17e7b179227288cb 100644 (file)
 #include "vm/jit/sparc64/md.h"
 #include "vm/jit/sparc64/md-abi.h"
 
-#include "native/native.h"
+#include "native/native.hpp"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/class.h"
 #include "vm/exceptions.hpp"
-#include "vm/field.h"
+#include "vm/field.hpp"
 #include "vm/initialize.h"
 #include "vm/options.h"
 #include "vm/references.h"
@@ -231,22 +231,9 @@ bool patcher_get_putfield(u1 *sp)
        if (!(fi = resolve_field_eager(uf)))
                return false;
 
-       /* if we show disassembly, we have to skip the nop's */
+       /* store the patched instruction on the stack */
 
-       if (opt_shownops) {
-               /* patch the field's offset into the instruction */
-
-               *((u4 *) (ra + 2 * 4)) |= (s2) (fi->offset & 0x00001fff);
-
-               /* synchronize instruction cache */
-
-               md_icacheflush(ra + 2 * 4, 1 * 4);
-       }
-       else {
-               /* otherwise store the patched instruction on the stack */
-
-               *((u4 *) (sp + 3 * 8)) |= (s2) (fi->offset & 0x00001fff);
-       }
+       *((u4 *) (sp + 3 * 8)) |= (s2) (fi->offset & 0x00001fff);
 
        return true;
 }
@@ -445,28 +432,11 @@ bool patcher_invokevirtual(u1 *sp)
        if (!(m = resolve_method_eager(um)))
                return false;
 
-       /* if we show disassembly, we have to skip the nop's */
-
-       if (opt_shownops) {
-               ra = ra + PATCHER_CALL_SIZE;
+       /* patch vftbl index */
 
-               /* patch vftbl index */
-
-               *((s4 *) (ra + 1 * 4)) |=
-                       (s4) ((OFFSET(vftbl_t, table[0]) +
-                                  sizeof(methodptr) * m->vftblindex) & 0x00001fff);
-
-               /* synchronize instruction cache */
-
-               md_icacheflush(ra + 1 * 4, 1 * 4);
-       }
-       else {
-               /* patch vftbl index */
-
-               *((s4 *) (sp + 3 * 8 + 4)) |=
-                       (s4) ((OFFSET(vftbl_t, table[0]) +
-                                  sizeof(methodptr) * m->vftblindex) & 0x00001fff);
-       }
+       *((s4 *) (sp + 3 * 8 + 4)) |=
+               (s4) ((OFFSET(vftbl_t, table[0]) +
+                          sizeof(methodptr) * m->vftblindex) & 0x00001fff);
 
        return true;
 }
@@ -501,42 +471,20 @@ bool patcher_invokeinterface(u1 *sp)
        if (!(m = resolve_method_eager(um)))
                return false;
 
-       /* if we show disassembly, we have to skip the nop's */
-
-       if (opt_shownops) {
-               ra = ra + PATCHER_CALL_SIZE;
+       /* patch interfacetable index */
 
-               /* patch interfacetable index */
-
-               *((s4 *) (ra + 1 * 4)) |= 
-                       (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
-                               sizeof(methodptr*) * m->clazz->index) & 0x00001fff);
-
-               /* patch method offset */
-
-               *((s4 *) (ra + 2 * 4)) |=
-                       (s4) ((sizeof(methodptr) * (m - m->clazz->methods)) & 0x00001fff);
-
-               /* synchronize instruction cache */
-
-               md_icacheflush(ra + 1 * 4, 2 * 4);
-       }
-       else {
-               /* patch interfacetable index */
-
-               *((s4 *) (sp + 3 * 8 + 4)) |=
-                       (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
-                               sizeof(methodptr*) * m->clazz->index) & 0x00001fff);
+       *((s4 *) (sp + 3 * 8 + 4)) |=
+               (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
+                          sizeof(methodptr*) * m->clazz->index) & 0x00001fff);
 
-               /* patch method offset */
+       /* patch method offset */
 
-               *((s4 *) (ra + 2 * 4)) |=
-                       (s4) ((sizeof(methodptr) * (m - m->clazz->methods)) & 0x00001fff);
+       *((s4 *) (ra + 2 * 4)) |=
+               (s4) ((sizeof(methodptr) * (m - m->clazz->methods)) & 0x00001fff);
 
-               /* synchronize instruction cache */
+       /* synchronize instruction cache */
 
-               md_icacheflush(ra + 2 * 4, 1 * 4);
-       }
+       md_icacheflush(ra + 2 * 4, 1 * 4);
 
        return true;
 }
@@ -614,11 +562,6 @@ bool patcher_checkcast_interface(u1 *sp)
        if (!(c = resolve_classref_eager(cr)))
                return false;
 
-       /* if we show disassembly, we have to skip the nop's */
-
-       if (opt_shownops)
-               ra = ra + PATCHER_CALL_SIZE;
-
        /* patch super class index */
 
        *((s4 *) (ra + 2 * 4)) |= (s4) (-(c->index) & 0x00001fff);
@@ -629,10 +572,7 @@ bool patcher_checkcast_interface(u1 *sp)
 
        /* synchronize instruction cache */
 
-       if (opt_shownops)
-               md_icacheflush(ra - 2 * 4, (6 + EXCEPTION_CHECK_INSTRUCTIONS) * 4);
-       else
-               md_icacheflush(ra, (4 + EXCEPTION_CHECK_INSTRUCTIONS) * 4);
+       md_icacheflush(ra, (4 + EXCEPTION_CHECK_INSTRUCTIONS) * 4);
 
        return true;
 }
@@ -667,11 +607,6 @@ bool patcher_instanceof_interface(u1 *sp)
        if (!(c = resolve_classref_eager(cr)))
                return false;
 
-       /* if we show disassembly, we have to skip the nop's */
-
-       if (opt_shownops)
-               ra = ra + PATCHER_CALL_SIZE;
-
        /* patch super class index */
 
        *((s4 *) (ra + 2 * 4)) |= (s4) ((c->index) & 0x00001fff);
@@ -681,10 +616,7 @@ bool patcher_instanceof_interface(u1 *sp)
 
        /* synchronize instruction cache */
 
-       if (opt_shownops)
-               md_icacheflush(ra - PATCHER_CALL_SIZE * 4, 8 * 4);
-       else
-               md_icacheflush(ra, 6 * 4);
+       md_icacheflush(ra, 6 * 4);
 
        return true;
 }
index 4ecac4876426e7fe74d17cd2ae4e1f63edb3ee48..b5c15689c40d8c5ade946a28a35491de2996e94e 100644 (file)
 
 #include "mm/memory.h"
 
-#include "native/native.h"
+#include "native/native.hpp"
 
 #include "toolbox/logging.h"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/exceptions.hpp"
 #include "vm/global.h"
 #include "vm/options.h"
 
 #include "vm/jit/abi.h"
 #include "vm/jit/cfg.h"
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/codegen-common.hpp"
 #include "vm/jit/parse.h"
-#include "vm/jit/show.h"
+#include "vm/jit/show.hpp"
 
 #if defined(ENABLE_DISASSEMBLER)
 # include "vm/jit/disass.h"
 #endif
 
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
 #include "vm/jit/stack.h"
 
 #if 0
index 4663cc034c585a40ca81119cee09e9bc7e44f372..803d2db11d83ed7ae3d5c3e5c561e6554613e1bd 100644 (file)
@@ -39,7 +39,7 @@ typedef struct stackelement_t stackelement_t;
 
 #include "vm/global.h"
 
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
 #include "vm/jit/reg.h"
 
 
@@ -161,12 +161,20 @@ struct stackelement_t {
 
 /* function prototypes ********************************************************/
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 bool stack_init(void);
 
 bool stack_analyse(jitdata *jd);
 
 void stack_javalocals_store(instruction *iptr, s4 *javalocals);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* _STACK_H */
 
 
index d58427ac4cf20f033dc83934ad4d4a46c0b003d8..54ec365dc43ccb5226d975451b2c6a0061ee0bcb 100644 (file)
 
 #include "vm/jit/stacktrace.hpp"
 
-#include "vm/global.h"                   /* required here for native includes */
-#include "native/jni.h"
 #include "native/llni.h"
 
 #include "threads/thread.hpp"
 
 #include "toolbox/logging.h"
 
-#include "vm/array.h"
-#include "vm/builtin.h"
+#include "vm/array.hpp"
+#include "vm/jit/builtin.hpp"
 #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/loader.hpp"
 #include "vm/method.h"
 #include "vm/options.h"
 #include "vm/string.hpp"
 #include "vm/vm.hpp"
 
 #include "vm/jit/asmpart.h"
-#include "vm/jit/codegen-common.h"
-#include "vm/jit/linenumbertable.h"
+#include "vm/jit/codegen-common.hpp"
+#include "vm/jit/linenumbertable.hpp"
 #include "vm/jit/methodheader.h"
 #include "vm/jit/methodtree.h"
 
@@ -1141,7 +1139,7 @@ void stacktrace_print(stacktrace_t *st)
 
                /* Get the line number. */
 
-               linenumber = linenumbertable_linenumber_for_pc(&m, ste->code, ste->pc);
+               linenumber = ste->code->linenumbertable->find(&m, ste->pc);
 
                stacktrace_print_entry(m, linenumber);
        }
@@ -1181,9 +1179,8 @@ void stacktrace_print_current(void)
                code = tmpsfi.code;
                m    = code->m;
 
-               /* Get the line number. */
-
-               linenumber = linenumbertable_linenumber_for_pc(&m, code, tmpsfi.xpc);
+               // Get the line number.
+               linenumber = code->linenumbertable->find(&m, tmpsfi.xpc);
 
                stacktrace_print_entry(m, linenumber);
        }
@@ -1226,9 +1223,8 @@ void stacktrace_print_of_thread(threadobject *t)
                code = tmpsfi.code;
                m    = code->m;
 
-               /* Get the line number. */
-
-               linenumber = linenumbertable_linenumber_for_pc(&m, code, tmpsfi.xpc);
+               // Get the line number.
+               linenumber = code->linenumbertable->find(&m, tmpsfi.xpc);
 
                stacktrace_print_entry(m, linenumber);
        }
index 376b597be468448f1443fa72099489fb44e0c392..d37064edac12fb8541ec1e09c2effe9ded79b847 100644 (file)
 #ifndef _STACKTRACE_HPP
 #define _STACKTRACE_HPP
 
-// FIXME Use C-linkage for now.
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /* forward typedefs ***********************************************************/
 
 typedef struct stackframeinfo_t   stackframeinfo_t;
@@ -50,7 +45,7 @@ typedef struct stacktrace_t       stacktrace_t;
 #include "vm/class.h"
 #include "vm/global.h"
 
-#include "vm/jit/code.h"
+#include "vm/jit/code.hpp"
 
 
 /* stackframeinfo **************************************************************
@@ -99,6 +94,11 @@ struct stacktrace_t {
 
 /* function prototypes ********************************************************/
 
+// FIXME Use C-linkage for now.
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 void                       stacktrace_stackframeinfo_add(stackframeinfo_t* sfi, void* pv, void* sp, void* ra, void* xpc);
 void                       stacktrace_stackframeinfo_remove(stackframeinfo_t *sfi);
 
@@ -132,7 +132,7 @@ u1 *md_get_pv_from_stackframe(u1 *sp);
 #endif
 
 #if defined(ENABLE_INTRP)
-u1 *intrp_md_stacktrace_get_returnaddress(u1 *sp, u4 framesize);
+void* intrp_md_stacktrace_get_returnaddress(void* sp, int32_t framesize);
 #endif
 
 #if defined(ENABLE_CYCLES_STATS)
diff --git a/src/vm/jit/stubs.cpp b/src/vm/jit/stubs.cpp
new file mode 100644 (file)
index 0000000..42a6c44
--- /dev/null
@@ -0,0 +1,439 @@
+/* src/vm/jit/stubs.cpp - JIT stubs
+
+   Copyright (C) 1996-2005, 2006, 2007, 2008
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+   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 machine dependent headers.
+#include "md.h"
+
+#include "mm/dumpmemory.hpp"
+
+#include "vm/method.h"
+#include "vm/options.h"
+
+#include "vm/jit/abi.h"
+#include "vm/jit/code.hpp"
+#include "vm/jit/codegen-common.hpp"
+#include "vm/jit/disass.h"
+#include "vm/jit/emit-common.hpp"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/show.hpp"
+#include "vm/jit/stubs.hpp"
+
+
+/**
+ * Wrapper for codegen_emit_stub_compiler.
+ *
+ * @param m Method object.
+ *
+ * @return Pointer to the compiler stub code.
+ */
+void* CompilerStub::generate(methodinfo *m)
+{
+       jitdata     *jd;
+       codegendata *cd;
+       ptrint      *d;                     /* pointer to data memory             */
+       u1          *c;                     /* pointer to code memory             */
+
+       // Create new dump memory area.
+       DumpMemoryArea dma;
+
+       /* allocate required data structures */
+
+       jd = (jitdata*) DumpMemory::allocate(sizeof(jitdata));
+
+       jd->m     = m;
+       jd->cd    = (codegendata*) DumpMemory::allocate(sizeof(codegendata));
+       jd->flags = 0;
+
+       /* get required compiler data */
+
+       cd = jd->cd;
+
+#if !defined(JIT_COMPILER_VIA_SIGNAL)
+       /* allocate code memory */
+
+       c = CNEW(u1, 3 * SIZEOF_VOID_P + get_code_size());
+
+       /* set pointers correctly */
+
+       d = (ptrint *) c;
+
+       cd->mcodebase = c;
+
+       c = c + 3 * SIZEOF_VOID_P;
+       cd->mcodeptr = c;
+
+       /* NOTE: The codeinfo pointer is actually a pointer to the
+          methodinfo (this fakes a codeinfo structure). */
+
+       d[0] = (ptrint) asm_call_jit_compiler;
+       d[1] = (ptrint) m;
+       d[2] = (ptrint) &d[1];                                    /* fake code->m */
+
+       /* call the emit function */
+
+       codegen_emit_stub_compiler(jd);
+
+#if defined(ENABLE_STATISTICS)
+       if (opt_stat)
+               count_cstub_len += 3 * SIZEOF_VOID_P + get_code_size();
+#endif
+
+       /* flush caches */
+
+       md_cacheflush(cd->mcodebase, 3 * SIZEOF_VOID_P + get_code_size());
+#else
+       /* Allocate code memory. */
+
+       c = CNEW(uint8_t, 2 * SIZEOF_VOID_P + get_code_size());
+
+       /* Set pointers correctly. */
+
+       d = (ptrint *) c;
+
+       cd->mcodebase = c;
+
+       c = c + 2 * SIZEOF_VOID_P;
+       cd->mcodeptr = c;
+
+       /* NOTE: The codeinfo pointer is actually a pointer to the
+          methodinfo (this fakes a codeinfo structure). */
+
+       d[0] = (ptrint) m;
+       d[1] = (ptrint) &d[0];                                    /* fake code->m */
+
+       /* Emit the trap instruction. */
+
+       emit_trap_compiler(cd);
+
+#if defined(ENABLE_STATISTICS)
+       if (opt_stat)
+               count_cstub_len += 2 * SIZEOF_VOID_P + get_code_size();
+#endif
+
+       /* Flush caches. */
+
+       md_cacheflush(cd->mcodebase, 2 * SIZEOF_VOID_P + get_code_size());
+#endif
+
+       /* return native stub code */
+
+       return c;
+}
+
+
+/**
+ * Free a compiler stub from memory.
+ *
+ * @param 
+ */
+void CompilerStub::remove(void* stub)
+{
+       // Pass size 1 to keep the intern function happy.
+       CFREE(stub, 1);
+}
+
+
+/* codegen_disassemble_nativestub **********************************************
+
+   Disassembles the generated builtin or native stub.
+
+*******************************************************************************/
+
+#if defined(ENABLE_DISASSEMBLER)
+static void codegen_disassemble_stub(methodinfo *m, u1 *start, u1 *end)
+{
+       printf("Stub code: ");
+       if (m->clazz != NULL)
+               utf_fprint_printable_ascii_classname(stdout, m->clazz->name);
+       else
+               printf("NULL");
+       printf(".");
+       utf_fprint_printable_ascii(stdout, m->name);
+       utf_fprint_printable_ascii(stdout, m->descriptor);
+       printf("\nLength: %d\n\n", (s4) (end - start));
+
+       DISASSEMBLE(start, end);
+}
+#endif
+
+
+/**
+ * Wrapper for codegen_emit_stub_native.
+ *
+ * @param m   Method object.
+ * @param bte Builtin function structure.
+ */
+void BuiltinStub::generate(methodinfo* m, builtintable_entry* bte)
+{
+       jitdata  *jd;
+       codeinfo *code;
+       int       skipparams;
+
+       // Create new dump memory area.
+       DumpMemoryArea dma;
+
+       /* Create JIT data structure. */
+
+       jd = jit_jitdata_new(m);
+
+       /* Get required compiler data. */
+
+       code = jd->code;
+
+       /* Stubs are non-leaf methods. */
+
+       code_unflag_leafmethod(code);
+
+       /* setup code generation stuff */
+
+       codegen_setup(jd);
+
+       /* Set the number of native arguments we need to skip. */
+
+       skipparams = 0;
+
+       /* generate the code */
+
+#if defined(ENABLE_JIT)
+# if defined(ENABLE_INTRP)
+       if (!opt_intrp) {
+# endif
+               assert(bte->fp != NULL);
+               codegen_emit_stub_native(jd, bte->md, bte->fp, skipparams);
+# if defined(ENABLE_INTRP)
+       }
+# endif
+#endif
+
+       /* reallocate the memory and finish the code generation */
+
+       codegen_finish(jd);
+
+       /* set the stub entry point in the builtin table */
+
+       bte->stub = code->entrypoint;
+
+#if defined(ENABLE_STATISTICS)
+       if (opt_stat)
+               size_stub_native += code->mcodelength;
+#endif
+
+#if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER)
+       /* disassemble native stub */
+
+       if (opt_DisassembleStubs) {
+               codegen_disassemble_stub(m,
+                                                                (u1 *) (ptrint) code->entrypoint,
+                                                                (u1 *) (ptrint) code->entrypoint + (code->mcodelength - jd->cd->dseglen));
+
+               /* show data segment */
+
+               if (opt_showddatasegment)
+                       dseg_display(jd);
+       }
+#endif /* !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER) */
+}
+
+
+/**
+ * Wrapper for codegen_emit_stub_native.
+ *
+ * @param m Method object of the native function.
+ * @param f Native function pointer.
+ *
+ * @return The codeinfo representing the stub code.
+ */
+codeinfo* NativeStub::generate(methodinfo* m, functionptr f)
+{
+       jitdata     *jd;
+       codeinfo    *code;
+       methoddesc  *md;
+       methoddesc  *nmd;       
+       int          skipparams;
+
+       // Create new dump memory area.
+       DumpMemoryArea dma;
+
+       /* Create JIT data structure. */
+
+       jd = jit_jitdata_new(m);
+
+       /* Get required compiler data. */
+
+       code = jd->code;
+
+       /* Stubs are non-leaf methods. */
+
+       code_unflag_leafmethod(code);
+
+       /* set the flags for the current JIT run */
+
+#if defined(ENABLE_PROFILING)
+       if (opt_prof)
+               jd->flags |= JITDATA_FLAG_INSTRUMENT;
+#endif
+
+       if (opt_verbosecall)
+               jd->flags |= JITDATA_FLAG_VERBOSECALL;
+
+       /* setup code generation stuff */
+
+#if defined(ENABLE_JIT)
+# if defined(ENABLE_INTRP)
+       if (!opt_intrp)
+# endif
+               reg_setup(jd);
+#endif
+
+       codegen_setup(jd);
+
+       /* create new method descriptor with additional native parameters */
+
+       md = m->parseddesc;
+
+       /* Set the number of native arguments we need to skip. */
+
+       if (m->flags & ACC_STATIC)
+               skipparams = 2;
+       else
+               skipparams = 1;
+       
+       nmd = (methoddesc*) DumpMemory::allocate(sizeof(methoddesc) - sizeof(typedesc) +
+                                                                                        md->paramcount * sizeof(typedesc) +
+                                                                                        skipparams * sizeof(typedesc));
+
+       nmd->paramcount = md->paramcount + skipparams;
+
+       nmd->params = (paramdesc*) DumpMemory::allocate(sizeof(paramdesc) * nmd->paramcount);
+
+       nmd->paramtypes[0].type = TYPE_ADR; /* add environment pointer            */
+
+       if (m->flags & ACC_STATIC)
+               nmd->paramtypes[1].type = TYPE_ADR; /* add class pointer              */
+
+       MCOPY(nmd->paramtypes + skipparams, md->paramtypes, typedesc,
+                 md->paramcount);
+
+#if defined(ENABLE_JIT)
+# if defined(ENABLE_INTRP)
+       if (!opt_intrp)
+# endif
+               /* pre-allocate the arguments for the native ABI */
+
+               md_param_alloc_native(nmd);
+#endif
+
+       /* generate the code */
+
+#if defined(ENABLE_JIT)
+# if defined(ENABLE_INTRP)
+       if (opt_intrp)
+               intrp_createnativestub(f, jd, nmd);
+       else
+# endif
+               codegen_emit_stub_native(jd, nmd, f, skipparams);
+#else
+       intrp_createnativestub(f, jd, nmd);
+#endif
+
+       /* reallocate the memory and finish the code generation */
+
+       codegen_finish(jd);
+
+#if defined(ENABLE_STATISTICS)
+       /* must be done after codegen_finish() */
+
+       if (opt_stat)
+               size_stub_native += code->mcodelength;
+#endif
+
+#if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER)
+       /* disassemble native stub */
+
+       if (opt_DisassembleStubs) {
+# if defined(ENABLE_DEBUG_FILTER)
+               if (m->filtermatches & SHOW_FILTER_FLAG_SHOW_METHOD)
+# endif
+               {
+                       codegen_disassemble_stub(m,
+                                                                        (u1 *) (ptrint) code->entrypoint,
+                                                                        (u1 *) (ptrint) code->entrypoint + (code->mcodelength - jd->cd->dseglen));
+
+                       /* show data segment */
+
+                       if (opt_showddatasegment)
+                               dseg_display(jd);
+               }
+       }
+#endif /* !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER) */
+
+       /* return native stub code */
+
+       return code;
+}
+
+
+/**
+ * Free a native stub from memory.
+ *
+ * @param stub Pointer to stub memory.
+ */    
+void NativeStub::remove(void* stub)
+{
+       // Pass size 1 to keep the intern function happy.
+       CFREE(stub, 1);
+}
+
+
+// Legacy C interface.
+
+extern "C" {
+       void*     CompilerStub_generate(methodinfo* m) { return CompilerStub::generate(m); }
+       void      CompilerStub_remove(void* stub) { CompilerStub::remove(stub); }
+
+       void      BuiltinStub_generate(methodinfo* m, builtintable_entry* bte) { BuiltinStub::generate(m, bte); }
+
+       void      NativeStub_remove(void* stub) { NativeStub::remove(stub); }
+}
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
diff --git a/src/vm/jit/stubs.hpp b/src/vm/jit/stubs.hpp
new file mode 100644 (file)
index 0000000..ac4041f
--- /dev/null
@@ -0,0 +1,99 @@
+/* src/vm/jit/stubs.hpp - JIT stubs
+
+   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 _STUBS_HPP
+#define _STUBS_HPP
+
+#include "config.h"
+
+#include <stdint.h>
+
+#include "vm/method.h"
+
+#include "vm/jit/code.hpp"
+
+
+#ifdef __cplusplus
+
+/**
+ * Class for compiler stub generation.
+ */
+class CompilerStub {
+public:
+       static inline int get_code_size();
+
+       static void* generate(methodinfo* m);
+       static void  remove(void* stub);
+};
+
+
+/**
+ * Class for builtin stub generation.
+ */
+class BuiltinStub {
+public:
+       static void generate(methodinfo* m, builtintable_entry* bte);
+};
+
+
+/**
+ * Class for native stub generation.
+ */
+class NativeStub {
+public:
+       static codeinfo* generate(methodinfo* m, functionptr f);
+       static void      remove(void* stub);
+};
+
+
+// Include machine dependent implementation.
+#include "md-stubs.hpp"
+
+#else
+
+// Legacy C interface.
+
+void*     CompilerStub_generate(methodinfo* m);
+void*     CompilerStub_remove(void* stub);
+void      BuiltinStub_generate(methodinfo* m, builtintable_entry* bte);
+void      NativeStub_remove(void* stub);
+
+#endif
+
+#endif // _STUBS_HPP
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
index 3a138e5ad5dcd8665020dad203de237b0bc6eab9..91a36557323fa150643bce6d55e14576d0fed7b9 100644 (file)
@@ -32,7 +32,6 @@
 
 #include "mm/memory.h"
 
-#include "native/jni.h"
 #include "native/llni.h"
 
 #include "threads/thread.hpp"
 #include "vm/string.hpp"
 #include "vm/utf8.h"
 
-#include "vm/jit/argument.h"
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/argument.hpp"
+#include "vm/jit/codegen-common.hpp"
 #include "vm/jit/trace.hpp"
-#include "vm/jit/show.h"
+#include "vm/jit/show.hpp"
 
 
 #if !defined(NDEBUG)
@@ -120,7 +119,7 @@ static char *trace_java_call_print_argument(methodinfo *m, char *logtext, s4 *lo
 
                /* Cast to java.lang.Object. */
 
-               o = (java_object_t *) (ptrint) imu.l;
+               o = (java_handle_t*) (uintptr_t) imu.l;
 
                /* Check return argument for java.lang.Class or
                   java.lang.String. */
@@ -136,7 +135,7 @@ static char *trace_java_call_print_argument(methodinfo *m, char *logtext, s4 *lo
 
                                /* realloc memory for string length */
 
-                               logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
+                               logtext = (char*) DumpMemory::reallocate(logtext, *logtextlen, *logtextlen + len);
                                *logtextlen += len;
 
                                /* convert to utf8 string and strcat it to the logtext */
@@ -166,7 +165,7 @@ static char *trace_java_call_print_argument(methodinfo *m, char *logtext, s4 *lo
 
                                /* realloc memory for string length */
 
-                               logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
+                               logtext = (char*) DumpMemory::reallocate(logtext, *logtextlen, *logtextlen + len);
                                *logtextlen += len;
 
                                /* strcat to the logtext */
@@ -202,7 +201,6 @@ void trace_java_call_enter(methodinfo *m, uint64_t *arg_regs, uint64_t *stack)
        s4          logtextlen;
        s4          i;
        s4          pos;
-       int32_t     dumpmarker;
 
        /* We don't trace builtin functions here because the argument
           passing happens via the native ABI and does not fit these
@@ -260,11 +258,11 @@ void trace_java_call_enter(methodinfo *m, uint64_t *arg_regs, uint64_t *stack)
                strlen("...(255)") +
                strlen(")");
 
-       /* allocate memory */
+       // Create new dump memory area.
+       DumpMemoryArea dma;
 
-       DMARKER;
-
-       logtext = DMNEW(char, logtextlen);
+       // TODO Use a std::string here.
+       logtext = (char*) DumpMemory::allocate(sizeof(char) * logtextlen);
 
        TRACEJAVACALLCOUNT++;
 
@@ -313,12 +311,7 @@ void trace_java_call_enter(methodinfo *m, uint64_t *arg_regs, uint64_t *stack)
 
        log_text(logtext);
 
-       /* release memory */
-
-       DRELEASE;
-
        TRACEJAVACALLINDENT++;
-
 }
 
 /* trace_java_call_exit ********************************************************
@@ -339,7 +332,6 @@ void trace_java_call_exit(methodinfo *m, uint64_t *return_regs)
        s4          i;
        s4          pos;
        imm_union   val;
-       int32_t     dumpmarker;
 
        /* We don't trace builtin functions here because the argument
           passing happens via the native ABI and does not fit these
@@ -384,11 +376,11 @@ void trace_java_call_exit(methodinfo *m, uint64_t *return_regs)
 
        logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
 
-       /* allocate memory */
+       // Create new dump memory area.
+       DumpMemoryArea dma;
 
-       DMARKER;
-
-       logtext = DMNEW(char, logtextlen);
+       // TODO Use a std::string here.
+       logtext = (char*) DumpMemory::allocate(sizeof(char) * logtextlen);
 
        /* generate the message */
 
@@ -419,10 +411,6 @@ void trace_java_call_exit(methodinfo *m, uint64_t *return_regs)
        }
 
        log_text(logtext);
-
-       /* release memory */
-
-       DRELEASE;
 }
 
 
@@ -437,7 +425,6 @@ void trace_exception(java_object_t *xptr, methodinfo *m, void *pos)
        char *logtext;
        s4    logtextlen;
        codeinfo *code;
-       int32_t   dumpmarker;
 
        /* calculate message length */
 
@@ -480,11 +467,11 @@ void trace_exception(java_object_t *xptr, methodinfo *m, void *pos)
 
        logtextlen += strlen("0");
 
-       /* allocate memory */
+       // Create new dump memory area.
+       DumpMemoryArea dma;
 
-       DMARKER;
-
-       logtext = DMNEW(char, logtextlen);
+       // TODO Use a std::string here.
+       logtext = (char*) DumpMemory::allocate(sizeof(char) * logtextlen);
 
        if (xptr) {
                strcpy(logtext, "Exception ");
@@ -550,10 +537,6 @@ void trace_exception(java_object_t *xptr, methodinfo *m, void *pos)
                strcat(logtext, "call_java_method");
 
        log_text(logtext);
-
-       /* release memory */
-
-       DRELEASE;
 }
 
 
@@ -567,7 +550,6 @@ void trace_exception_builtin(java_handle_t* h)
 {
        char                *logtext;
        s4                   logtextlen;
-       int32_t              dumpmarker;
 
        java_lang_Throwable jlt(h);
 
@@ -596,11 +578,10 @@ void trace_exception_builtin(java_handle_t* h)
                logtextlen += strlen("(nil)");
        }
 
-       /* allocate memory */
+       // Create new dump memory area.
+       DumpMemoryArea dma;
 
-       DMARKER;
-
-       logtext = DMNEW(char, logtextlen);
+       logtext = (char*) DumpMemory::allocate(sizeof(char) * logtextlen);
 
        strcpy(logtext, "Builtin exception thrown: ");
 
@@ -621,10 +602,6 @@ void trace_exception_builtin(java_handle_t* h)
        }
 
        log_text(logtext);
-
-       /* release memory */
-
-       DRELEASE;
 }
 
 } // extern "C"
index c6f441d5cc5d4b3debaab66b366ce8106486fbbf..1ac7ffe7e71e6d016b8d3a8594b75da78803f214 100644 (file)
@@ -29,6 +29,7 @@
 
 /* Include machine dependent trap stuff. */
 
+#include "md.h"
 #include "md-trap.h"
 
 #include "mm/memory.h"
 #include "vm/os.hpp"
 #include "vm/vm.hpp"
 
-#include "vm/jit/code.h"
+#include "vm/jit/asmpart.h"
+#include "vm/jit/code.hpp"
 #include "vm/jit/disass.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/executionstate.h"
+#include "vm/jit/jit.hpp"
 #include "vm/jit/methodtree.h"
-#include "vm/jit/patcher-common.h"
-#include "vm/jit/replace.h"
+#include "vm/jit/patcher-common.hpp"
+#include "vm/jit/replace.hpp"
 #include "vm/jit/stacktrace.hpp"
 
 
@@ -96,6 +99,7 @@ void trap_init(void)
  */
 void* trap_handle(int type, intptr_t val, void *pv, void *sp, void *ra, void *xpc, void *context)
 {
+       executionstate_t  es;
        stackframeinfo_t  sfi;
        int32_t           index;
        java_handle_t    *o;
@@ -116,6 +120,19 @@ void* trap_handle(int type, intptr_t val, void *pv, void *sp, void *ra, void *xp
        o = NULL;
        m = NULL;
 
+#if defined(__ALPHA__) || defined(__ARM__) || defined(__I386__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__X86_64__)
+# if !defined(NDEBUG)
+       /* Perform a sanity check on our execution state functions. */
+
+       executionstate_sanity_check(context);
+# endif
+
+       /* Read execution state from current context. */
+
+       es.code = NULL;
+       md_executionstate_read(&es, context);
+#endif
+
        /* wrap the value into a handle if it is a reference */
        /* BEFORE: creating stackframeinfo */
 
@@ -223,6 +240,63 @@ void* trap_handle(int type, intptr_t val, void *pv, void *sp, void *ra, void *xp
 
        stacktrace_stackframeinfo_remove(&sfi);
 
+#if defined(__ALPHA__) || defined(__ARM__) || defined(__I386__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__X86_64__)
+       /* Update execution state and set registers. */
+       /* AFTER: removing stackframeinfo */
+
+       switch (type) {
+       case TRAP_COMPILER:
+               // The normal case for a compiler trap is to jump directly to
+               // the newly compiled method.
+
+               if (p != NULL) {
+                       es.pc = (uint8_t *) (uintptr_t) p;
+                       es.pv = (uint8_t *) (uintptr_t) p;
+                       break;
+               }
+
+               // In case of an exception during JIT compilation, we fetch
+               // the exception here and proceed with exception handling.
+
+               java_handle_t *e = exceptions_get_and_clear_exception();
+               assert(e != NULL);
+
+               // Get and set the PV from the parent Java method.
+
+               es.pv = md_codegen_get_pv_from_pc(ra);
+
+               // XXX: Make the code below a fall-through to default case!
+
+               es.intregs[REG_ITMP1_XPTR] = (uintptr_t) LLNI_DIRECT(e);
+               es.intregs[REG_ITMP2_XPC]  = (uintptr_t) xpc;
+               es.pc                      = (uint8_t *) (uintptr_t) asm_handle_exception;
+               break;
+
+       case TRAP_PATCHER:
+               // The normal case for a patcher trap is to continue execution at
+               // the trap instruction. On some archs the PC may point after the
+               // trap instruction, so we reset it here.
+
+               if (p == NULL) {
+                       es.pc = (uint8_t *) (uintptr_t) xpc;
+                       break;
+               }
+
+               /* fall-through */
+
+       default:
+               if (p != NULL) {
+                       es.intregs[REG_ITMP1_XPTR] = (uintptr_t) LLNI_DIRECT(p);
+                       es.intregs[REG_ITMP2_XPC]  = (uintptr_t) xpc;
+                       es.pc                      = (uint8_t *) (uintptr_t) asm_handle_exception;
+               }
+       }
+
+       /* Write back execution state to current context. */
+
+       md_executionstate_write(&es, context);
+#endif
+
        /* unwrap and return the exception object */
        /* AFTER: removing stackframeinfo */
 
index f574a4c07f4a7ad310a015a1d7279bb6c1e811b2..7b2cdd1997bf5a66927cdd8c6c77afb8d1c0d03a 100644 (file)
@@ -32,7 +32,7 @@
 #include "vm/exceptions.hpp"
 #include "vm/globals.hpp"
 
-#include "vm/jit/show.h"
+#include "vm/jit/show.hpp"
 
 #include "typecheck-common.h"
 
index fd3f6ab6fe631fdd42b242a38f639564314a3d1b..226113f165b1b75dcb179c3bbdd2cdc0a9ad7d97 100644 (file)
@@ -32,7 +32,7 @@
 
 #include <assert.h>
 
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
 
 
 /****************************************************************************/
index 90c693094bb84e235e8c1a259ccefc921ecb7a16..b978516b5f6a33422dbcbfab09b5c6b62908d07b 100644 (file)
 
 #include "vm/types.h"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "mm/memory.h"
 
-#include "vm/array.h"
+#include "vm/array.hpp"
 #include "vm/exceptions.hpp"
 #include "vm/global.h"
 #include "vm/globals.hpp"
 #include "vm/primitive.hpp"
 
 #include "vm/jit/parse.h"
-#include "vm/jit/show.h"
+#include "vm/jit/show.hpp"
 #include "vm/jit/stack.h"
 #include "vm/jit/verify/typecheck-common.h"
 
index 1cfeba69da3483b2484e7b0e57817c183671a10c..f63d37fd808ca00a37345f385b167e573b5f092b 100644 (file)
 
 #include "mm/memory.h"
 
-#include "native/native.h"
+#include "native/native.hpp"
 
 #include "toolbox/logging.h"
 
 #include "vm/access.h"
-#include "vm/array.h"
-#include "vm/builtin.h"
+#include "vm/array.hpp"
+#include "vm/jit/builtin.hpp"
 #include "vm/exceptions.hpp"
 #include "vm/globals.hpp"
-#include "vm/loader.h"
+#include "vm/loader.hpp"
 #include "vm/options.h"
 #include "vm/primitive.hpp"
 #include "vm/resolve.h"
 #include "vm/vm.hpp"
 
-#include "vm/jit/jit.h"
-#include "vm/jit/show.h"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/show.hpp"
 #include "vm/jit/parse.h"
 
 #include "vm/jit/verify/typecheck-typeinferer.h"
index 530a5e1e2870c45bcacccd9adfd4841c1c5f9dcf..6684ac9393229ebe3cb47dad02a8fc5b17d7d128 100644 (file)
@@ -36,7 +36,7 @@
 #include "config.h"
 
 #include "vm/global.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
 
 
 /* function prototypes ********************************************************/
index afe2fb62108170213373322bb9e052f0a99189ad..51b789fdedd5caec7d7bafb9beb5589454bdf9df 100644 (file)
@@ -143,24 +143,24 @@ error reporting.
 
 #include "mm/memory.h"
 
-#include "native/native.h"
+#include "native/native.hpp"
 
 #include "toolbox/logging.h"
 
 #include "vm/access.h"
-#include "vm/array.h"
-#include "vm/builtin.h"
+#include "vm/array.hpp"
+#include "vm/jit/builtin.hpp"
 #include "vm/exceptions.hpp"
 #include "vm/global.h"
 #include "vm/globals.hpp"
-#include "vm/loader.h"
+#include "vm/loader.hpp"
 #include "vm/options.h"
 #include "vm/primitive.hpp"
 #include "vm/resolve.h"
 
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
 #include "vm/jit/parse.h"
-#include "vm/jit/show.h"
+#include "vm/jit/show.hpp"
 
 #include <typecheck-common.h>
 
index 01492ea53e041e4314d43d9caaea139a5b253509..dac58ca419cd757c977cf3182d0663e6c9bb6e7b 100644 (file)
@@ -1,9 +1,7 @@
 /* src/vm/jit/verify/typecheck.h - type checking header
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
-   C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
-   E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
-   J. Wenninger, Institut f. Computersprachen - TU Wien
+   Copyright (C) 1996-2005, 2006, 2008
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
 
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Christian Thalinger
-
-
 */
 
 
 #include "config.h"
 
 #include "vm/global.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
 
 
 /* function prototypes ********************************************************/
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #if defined(ENABLE_VERIFIER)
 bool typecheck(jitdata *jd);
 bool typecheck_stackbased(jitdata *jd);
 #endif
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* _TYPECHECK_H */
 
 
index b39ca9a61716592f1f56c168bb61d9c57eccc151..6cf7f6556fc678324481529421d80a62c1e123ee 100644 (file)
 
 #include "toolbox/logging.h"
 
-#include "vm/array.h"
+#include "vm/array.hpp"
 #include "vm/class.h"
 #include "vm/descriptor.h"
 #include "vm/exceptions.hpp"
 #include "vm/globals.hpp"
-#include "vm/loader.h"
+#include "vm/loader.hpp"
 #include "vm/primitive.hpp"
 #include "vm/resolve.h"
 
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
 #include "vm/jit/verify/typeinfo.h"
 
 
index 338afc1829057be135aa6146e8f525e7043f1f88..354c92ec1f3ca273b4dde3dacf3d225f1a381498 100644 (file)
@@ -57,6 +57,7 @@ libarch_la_SOURCES = \
        \
        md-abi.c \
        md-abi.h \
+       md-stubs.hpp \
        md-trap.h \
        md.c \
        md.h
index 331e3afc70b53391ac9ffb90e9f36a6a05819991..f31db1429f5303040e48e65a2f63d290f562d365 100644 (file)
@@ -35,8 +35,6 @@
 
 /* define architecture features ***********************************************/
 
-#define U8_AVAILABLE                     1
-
 #define SUPPORT_DIVISION                 1
 #define SUPPORT_LONG                     1
 
index 680c82650f30e4b871a31c5c9d07386519230558..c2cbea33fb035eb017d512e0ec0540e6992cc246 100644 (file)
 
 #include "mm/memory.h"
 
-#include "native/jni.h"
-#include "native/localref.h"
-#include "native/native.h"
+#include "native/localref.hpp"
+#include "native/native.hpp"
 
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/exceptions.hpp"
 #include "vm/global.h"
-#include "vm/loader.h"
+#include "vm/loader.hpp"
 #include "vm/options.h"
 #include "vm/primitive.hpp"
 #include "vm/statistics.h"
 
 #include "vm/jit/abi.h"
 #include "vm/jit/asmpart.h"
-#include "vm/jit/code.h"
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/code.hpp"
+#include "vm/jit/codegen-common.hpp"
 #include "vm/jit/dseg.h"
-#include "vm/jit/emit-common.h"
-#include "vm/jit/jit.h"
-#include "vm/jit/linenumbertable.h"
+#include "vm/jit/emit-common.hpp"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/linenumbertable.hpp"
 #include "vm/jit/methodheader.h"
 #include "vm/jit/parse.h"
-#include "vm/jit/patcher-common.h"
+#include "vm/jit/patcher-common.hpp"
 #include "vm/jit/reg.h"
-#include "vm/jit/replace.h"
+#include "vm/jit/replace.hpp"
 #include "vm/jit/stacktrace.hpp"
 #include "vm/jit/trap.h"
 
index 17d4edbd748369d93070e0fa29d4b40922262ddf..53e005f2cf60d4beaaae2b7e379ef0177641a8e9 100644 (file)
@@ -1,9 +1,7 @@
 /* src/vm/jit/x86_64/codegen.h - code generation macros for x86_64
 
-   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.
 
@@ -36,7 +34,7 @@
 
 #include "vm/jit/x86_64/emit.h"
 
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
 
 
 /* additional functions and macros to generate code ***************************/
     } while (0)
 
 
-/* stub defines ***************************************************************/
-
-#define COMPILERSTUB_CODESIZE    8
-
-
 /* macros to create code ******************************************************/
 
 #define M_BYTE1(a) \
index 92bf938ab92ce85e360fa6e46c0b711bf6d6f3f6..906a01e89d213e52f76d8435c77c2949852174c2 100644 (file)
 
 #include "mm/memory.h"
 
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
 
 #include "vm/options.h"
 
 #include "vm/jit/abi.h"
 #include "vm/jit/abi-asm.h"
 #include "vm/jit/asmpart.h"
-#include "vm/jit/codegen-common.h"
-#include "vm/jit/emit-common.h"
-#include "vm/jit/jit.h"
-#include "vm/jit/patcher-common.h"
-#include "vm/jit/replace.h"
+#include "vm/jit/codegen-common.hpp"
+#include "vm/jit/emit-common.hpp"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/patcher-common.hpp"
+#include "vm/jit/replace.hpp"
 #include "vm/jit/trace.hpp"
 #include "vm/jit/trap.h"
 
index 34bb44d055f219a0e1007c07b77387609160ddf6..1669fd52046742272e7478993237ad9713227bf8 100644 (file)
@@ -31,8 +31,8 @@
 #include "config.h"
 #include "vm/types.h"
 
-#include "vm/jit/codegen-common.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/codegen-common.hpp"
+#include "vm/jit/jit.hpp"
 
 
 /* macros to create code ******************************************************/
index 38d1306e6c953e700a2850379f96c728b9421cb2..5036ff2ef64da28a635ca2bb0d7f61670ae04b61 100644 (file)
@@ -39,7 +39,7 @@
 
 #include "threads/thread.hpp"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/signallocal.h"
 
 #include "vm/jit/asmpart.h"
@@ -70,7 +70,6 @@ void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
        int             type;
        intptr_t        val;
        void           *p;
-       java_object_t  *o;
 
        _uc = (ucontext_t *) _p;
        _mc = &_uc->uc_mcontext;
@@ -187,23 +186,9 @@ void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
 
        if (type == TRAP_COMPILER) {
                if (p == NULL) {
-                       o = builtin_retrieve_exception();
-
                        _mc->gregs[REG_RSP] = (uintptr_t) sp;    /* Remove RA from stack. */
-
-                       _mc->gregs[REG_RAX] = (uintptr_t) o;
-                       _mc->gregs[REG_R10] = (uintptr_t) xpc;           /* REG_ITMP2_XPC */
-                       _mc->gregs[REG_RIP] = (uintptr_t) asm_handle_exception;
-               }
-               else {
-                       _mc->gregs[REG_RIP] = (uintptr_t) p;
                }
        }
-       else {
-               _mc->gregs[REG_RAX] = (uintptr_t) p;
-               _mc->gregs[REG_R10] = (uintptr_t) xpc;               /* REG_ITMP2_XPC */
-               _mc->gregs[REG_RIP] = (uintptr_t) asm_handle_exception;
-       }
 }
 
 
@@ -224,7 +209,6 @@ void md_signal_handler_sigfpe(int sig, siginfo_t *siginfo, void *_p)
        u1             *xpc;
        int             type;
        intptr_t        val;
-       void           *p;
 
        _uc = (ucontext_t *) _p;
        _mc = &_uc->uc_mcontext;
@@ -244,13 +228,7 @@ void md_signal_handler_sigfpe(int sig, siginfo_t *siginfo, void *_p)
 
        /* Handle the trap. */
 
-       p = trap_handle(type, val, pv, sp, ra, xpc, _p);
-
-       /* set registers */
-
-       _mc->gregs[REG_RAX] = (intptr_t) p;
-       _mc->gregs[REG_R10] = (intptr_t) xpc;                    /* REG_ITMP2_XPC */
-       _mc->gregs[REG_RIP] = (intptr_t) asm_handle_exception;
+       trap_handle(type, val, pv, sp, ra, xpc, _p);
 }
 
 
@@ -270,7 +248,6 @@ void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p)
        u1             *xpc;
        int             type;
        intptr_t        val;
-       void           *p;
 
        _uc = (ucontext_t *) _p;
        _mc = &_uc->uc_mcontext;
@@ -290,15 +267,7 @@ void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p)
 
        /* Handle the trap. */
 
-       p = trap_handle(type, val, pv, sp, ra, xpc, _p);
-
-       /* set registers */
-
-       if (p != NULL) {
-               _mc->gregs[REG_RAX] = (intptr_t) p;
-               _mc->gregs[REG_R10] = (intptr_t) xpc;                /* REG_ITMP2_XPC */
-               _mc->gregs[REG_RIP] = (intptr_t) asm_handle_exception;
-       }
+       trap_handle(type, val, pv, sp, ra, xpc, _p);
 }
 
 
index d0ef903056b2c0a7fdbfa0b999ea69f7f1390982..fd248a596b4743b2fee491ed2acc697a56b58653 100644 (file)
@@ -32,7 +32,7 @@
 #include "vm/global.h"
 
 #include "vm/jit/abi.h"
-#include "vm/jit/jit.h" /* for REG_* (maybe can be removed) */
+#include "vm/jit/jit.hpp" /* for REG_* (maybe can be removed) */
 #include "vm/jit/stack.h"
 
 
diff --git a/src/vm/jit/x86_64/md-stubs.hpp b/src/vm/jit/x86_64/md-stubs.hpp
new file mode 100644 (file)
index 0000000..521a814
--- /dev/null
@@ -0,0 +1,56 @@
+/* src/vm/jit/x86_64/md-stubs.hpp - x86_64 JIT stubs
+
+   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 _MD_STUBS_HPP
+#define _MD_STUBS_HPP
+
+#include "config.h"
+
+
+/**
+ * Return the code size of a compiler on a x86_64 architecture.
+ *
+ * @return Code size in bytes.
+ */
+int CompilerStub::get_code_size()
+{
+       return 8;
+}
+
+#endif // _MD_STUBS_HPP
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
index 75a61687a8a2e4126f4d47d1a4ea1c557f4f2341..586550cfd485340406a80c301f65564c815e50f2 100644 (file)
@@ -33,8 +33,8 @@
 
 #include "vm/vm.hpp"
 
-#include "vm/jit/codegen-common.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/codegen-common.hpp"
+#include "vm/jit/jit.hpp"
 
 
 /* md_init *********************************************************************
index f60e9720f6ba583088a9c6257c161879b7ed3439..6495479a83f794fcdccf442809275630f85cf087 100644 (file)
@@ -1,6 +1,7 @@
 /* src/vm/jit/x86_64/md.h - machine dependent x86_64 functions
 
    Copyright (C) 1996-2005, 2006, 2007, 2008
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
 
@@ -30,7 +31,7 @@
 #include <assert.h>
 #include <stdint.h>
 
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/codegen-common.hpp"
 #include "vm/jit/methodtree.h"
 
 
@@ -82,9 +83,10 @@ inline static void *md_codegen_get_pv_from_pc(void *ra)
 
 *******************************************************************************/
 
-inline static void md_cacheflush(u1 *addr, s4 nbytes)
+inline static void md_cacheflush(void* addr, int nbytes)
 {
-       /* do nothing */
+       // Compiler optimization barrier (see PR97).
+       __asm__ __volatile__ ("" : : : "memory");
 }
 
 
@@ -94,9 +96,10 @@ inline static void md_cacheflush(u1 *addr, s4 nbytes)
 
 *******************************************************************************/
 
-inline static void md_icacheflush(u1 *addr, s4 nbytes)
+inline static void md_icacheflush(void* addr, int nbytes)
 {
-       /* do nothing */
+       // Compiler optimization barrier (see PR97).
+       __asm__ __volatile__ ("" : : : "memory");
 }
 
 
@@ -106,9 +109,10 @@ inline static void md_icacheflush(u1 *addr, s4 nbytes)
 
 *******************************************************************************/
 
-inline static void md_dcacheflush(u1 *addr, s4 nbytes)
+inline static void md_dcacheflush(void* addr, int nbytes)
 {
-       /* do nothing */
+       // Compiler optimization barrier (see PR97).
+       __asm__ __volatile__ ("" : : : "memory");
 }
 
 #endif /* _VM_JIT_X86_64_MD_H */
index 18e81ddc69e2c9677b44443dfbe1786e16eea900..b4a3805ccc51af617020b2b55c0358c17d38193e 100644 (file)
 #include "vm/types.h"
 
 #include "vm/jit/x86_64/codegen.h"
+#include "vm/jit/x86_64/md.h"
 
 #include "mm/memory.h"
 
-#include "native/native.h"
+#include "native/native.hpp"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/class.h"
-#include "vm/field.h"
+#include "vm/field.hpp"
 #include "vm/initialize.h"
 #include "vm/options.h"
 #include "vm/references.h"
 #include "vm/resolve.h"
 
-#include "vm/jit/patcher-common.h"
-
-
-#define PATCH_BACK_ORIGINAL_MCODE \
-    do { \
-        *((uint16_t *) pr->mpc) = (uint16_t) pr->mcode; \
-    } while (0)
+#include "vm/jit/patcher-common.hpp"
 
 
 /* patcher_patch_code **********************************************************
@@ -60,7 +55,8 @@
 
 void patcher_patch_code(patchref_t *pr)
 {
-       PATCH_BACK_ORIGINAL_MCODE;
+       *((uint16_t*) pr->mpc) = (uint16_t) pr->mcode;
+       md_icacheflush((void*) pr->mpc, PATCHER_CALL_SIZE);
 }
 
 
@@ -90,23 +86,23 @@ void patcher_patch_code(patchref_t *pr)
 
 bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
 {
-       constant_classref *cr;
-       intptr_t          *datap;
-       classinfo         *c;
+       constant_classref* cr    = (constant_classref*) pr->ref;
+       uintptr_t*         datap = (uintptr_t*)         pr->datap;
 
-       cr    = (constant_classref *) pr->ref;
-       datap = (intptr_t *)          pr->datap;
+       // Resolve the class.
+       classinfo* c = resolve_classref_eager(cr);
 
-       /* get the classinfo */
-
-       if (!(c = resolve_classref_eager(cr)))
+       if (c == NULL)
                return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
+       // Patch the class.
+       *datap = (uintptr_t) c;
 
-       /* patch the classinfo pointer */
+       // Synchronize data cache.
+       md_dcacheflush((void*) pr->datap, SIZEOF_VOID_P);
 
-       *datap = (intptr_t) c;
+       // Patch back the original code.
+       patcher_patch_code(pr);
 
        return true;
 }
@@ -123,25 +119,23 @@ bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
 
 bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
 {
-       constant_classref *cr;
-       intptr_t          *datap;
-       classinfo         *c;
-
-       /* get stuff from the stack */
+       constant_classref* cr    = (constant_classref*) pr->ref;
+       uintptr_t*         datap = (uintptr_t*)         pr->datap;
 
-       cr    = (constant_classref *) pr->ref;
-       datap = (intptr_t *)          pr->datap;
+       // Resolve the field.
+       classinfo* c = resolve_classref_eager(cr);
 
-       /* get the fieldinfo */
-
-       if (!(c = resolve_classref_eager(cr)))
+       if (c == NULL)
                return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
+       // Patch super class' vftbl.
+       *datap = (uintptr_t) c->vftbl;
 
-       /* patch super class' vftbl */
+       // Synchronize data cache.
+       md_dcacheflush((void*) pr->datap, SIZEOF_VOID_P);
 
-       *datap = (intptr_t) c->vftbl;
+       // Patch back the original code.
+       patcher_patch_code(pr);
 
        return true;
 }
@@ -157,31 +151,26 @@ bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
 
 bool patcher_resolve_classref_to_flags(patchref_t *pr)
 {
-       constant_classref *cr;
-       int32_t           *datap;
-       classinfo         *c;
-       uint8_t           *ra;
-
-       cr    = (constant_classref *) pr->ref;
-       datap = (int32_t *)           pr->datap;
-       ra    = (uint8_t *)           pr->mpc;
+       constant_classref* cr    = (constant_classref*) pr->ref;
+/*     int32_t*           datap = (int32_t*)           pr->datap; */
+       uint8_t*           ra    = (uint8_t*)           pr->mpc;
 
-       /* get the fieldinfo */
+       // Resolve the field.
+       classinfo* c = resolve_classref_eager(cr);
 
-       if (!(c = resolve_classref_eager(cr)))
+       if (c == NULL)
                return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
-
-       /* if we show disassembly, we have to skip the nop's */
-
-       if (opt_shownops)
-               ra = ra + PATCHER_CALL_SIZE;
+       // Patch class flags.
+/*     *datap = c->flags; */
+       *((int32_t*) (ra + 2)) = c->flags;
 
-       /* patch class flags */
+       // Synchronize data cache.
+/*     md_dcacheflush(datap, sizeof(int32_t)); */
+       md_icacheflush(ra + 2, sizeof(int32_t));
 
-/*     *datap = c->flags; */
-       *((int32_t *) (ra + 2)) = c->flags;
+       // Patch back the original code.
+       patcher_patch_code(pr);
 
        return true;
 }
@@ -199,29 +188,28 @@ bool patcher_resolve_classref_to_flags(patchref_t *pr)
 
 bool patcher_get_putstatic(patchref_t *pr)
 {
-       unresolved_field *uf;
-       intptr_t         *datap;
-       fieldinfo        *fi;
+       unresolved_field* uf    = (unresolved_field*) pr->ref;
+       uintptr_t*        datap = (uintptr_t*)        pr->datap;
 
-       uf    = (unresolved_field *) pr->ref;
-       datap = (intptr_t *)         pr->datap;
+       // Resolve the field.
+       fieldinfo* fi = resolve_field_eager(uf);
 
-       /* get the fieldinfo */
-
-       if (!(fi = resolve_field_eager(uf)))
+       if (fi == NULL)
                return false;
 
-       /* check if the field's class is initialized */
-
+       // Check if the field's class is initialized/
        if (!(fi->clazz->state & CLASS_INITIALIZED))
                if (!initialize_class(fi->clazz))
                        return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
+       // Patch the field value's address.
+       *datap = (uintptr_t) fi->value;
 
-       /* patch the field value's address */
+       // Synchronize data cache.
+       md_dcacheflush((void*) pr->datap, SIZEOF_VOID_P);
 
-       *datap = (intptr_t) fi->value;
+       // Patch back the original code.
+       patcher_patch_code(pr);
 
        return true;
 }
@@ -238,50 +226,38 @@ bool patcher_get_putstatic(patchref_t *pr)
 
 bool patcher_get_putfield(patchref_t *pr)
 {
-       uint8_t          *ra;
-       unresolved_field *uf;
-       fieldinfo        *fi;
-       uint8_t           byte;
-
-       ra = (uint8_t *)          pr->mpc;
-       uf = (unresolved_field *) pr->ref;
+       uint8_t*          pc = (uint8_t*)          pr->mpc;
+       unresolved_field* uf = (unresolved_field*) pr->ref;
 
-       /* get the fieldinfo */
+       // Resolve the field.
+       fieldinfo* fi = resolve_field_eager(uf);
 
-       if (!(fi = resolve_field_eager(uf)))
+       if (fi == NULL)
                return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
-
-       /* if we show disassembly, we have to skip the nop's */
-
-       if (opt_shownops)
-               ra = ra + PATCHER_CALL_SIZE;
-
-       /* Patch the field's offset: we check for the field type, because
-          the instructions have different lengths. */
-
+       // Patch the field's offset: we check for the field type, because
+       // the instructions have different lengths.
        if (IS_INT_LNG_TYPE(fi->type)) {
-               /* Check for special case: %rsp or %r12 as base register. */
-
-               byte = *(ra + 3);
-
-               if (byte == 0x24)
-                       *((int32_t *) (ra + 4)) = fi->offset;
+               // Check for special case: %rsp or %r12 as base register.
+               if (pc[3] == 0x24)
+                       *((int32_t*) (pc + 4)) = fi->offset;
                else
-                       *((int32_t *) (ra + 3)) = fi->offset;
+                       *((int32_t*) (pc + 3)) = fi->offset;
        }
        else {
-               /* Check for special case: %rsp or %r12 as base register. */
-
-               byte = *(ra + 5);
-
-               if (byte == 0x24)
-                       *((int32_t *) (ra + 6)) = fi->offset;
+               // Check for special case: %rsp or %r12 as base register.
+               if (pc[5] == 0x24)
+                       *((int32_t*) (pc + 6)) = fi->offset;
                else
-                       *((int32_t *) (ra + 5)) = fi->offset;
+                       *((int32_t*) (pc + 5)) = fi->offset;
        }
 
+       // Synchronize instruction cache.
+       md_icacheflush(pc, 6 + sizeof(int32_t));
+
+       // Patch back the original code.
+       patcher_patch_code(pr);
+
        return true;
 }
 
@@ -297,51 +273,37 @@ bool patcher_get_putfield(patchref_t *pr)
 
 bool patcher_putfieldconst(patchref_t *pr)
 {
-       uint8_t          *ra;
-       unresolved_field *uf;
-       fieldinfo        *fi;
-       uint8_t           byte;
+       uint8_t*          pc = (uint8_t*)          pr->mpc;
+       unresolved_field* uf = (unresolved_field*) pr->ref;
 
-       ra = (uint8_t *)          pr->mpc;
-       uf = (unresolved_field *) pr->ref;
+       // Resolve the field.
+       fieldinfo* fi = resolve_field_eager(uf);
 
-       /* get the fieldinfo */
-
-       if (!(fi = resolve_field_eager(uf)))
+       if (fi == NULL)
                return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
-
-       /* if we show disassembly, we have to skip the nop's */
-
-       if (opt_shownops)
-               ra = ra + PATCHER_CALL_SIZE;
-
-       /* patch the field's offset */
-
+       // Patch the field's offset.
        if (IS_2_WORD_TYPE(fi->type) || IS_ADR_TYPE(fi->type)) {
-               /* handle special case when the base register is %r12 */
-
-               byte = *(ra + 12);
-
-               if (byte == 0x94) {
-                       *((uint32_t *) (ra + 14))      = fi->offset;
-               }
-               else {
-                       *((uint32_t *) (ra + 13))      = fi->offset;
-               }
+               // Handle special case when the base register is %r12.
+               if (pc[12] == 0x94)
+                       *((uint32_t*) (pc + 14)) = fi->offset;
+               else
+                       *((uint32_t*) (pc + 13)) = fi->offset;
        }
        else {
-               /* handle special case when the base register is %r12 */
-
-               byte = *(ra + 2);
-
-               if (byte == 0x84)
-                       *((uint32_t *) (ra + 4)) = fi->offset;
+               // Handle special case when the base register is %r12.
+               if (pc[2] == 0x84)
+                       *((uint32_t*) (pc + 4)) = fi->offset;
                else
-                       *((uint32_t *) (ra + 3)) = fi->offset;
+                       *((uint32_t*) (pc + 3)) = fi->offset;
        }
 
+       // Synchronize instruction cache.
+       md_icacheflush(pc, 14 + sizeof(int32_t));
+
+       // Patch back the original code.
+       patcher_patch_code(pr);
+
        return true;
 }
 
@@ -358,25 +320,23 @@ bool patcher_putfieldconst(patchref_t *pr)
 
 bool patcher_invokestatic_special(patchref_t *pr)
 {
-       unresolved_method *um;
-       intptr_t          *datap;
-       methodinfo        *m;
-
-       /* get stuff from the stack */
+       unresolved_method* um    = (unresolved_method*) pr->ref;
+       uintptr_t*         datap = (uintptr_t*)         pr->datap;
 
-       um    = (unresolved_method *) pr->ref;
-       datap = (intptr_t *)          pr->datap;
+       // Resolve the method.
+       methodinfo* m = resolve_method_eager(um);
 
-       /* get the fieldinfo */
-
-       if (!(m = resolve_method_eager(um)))
+       if (m == NULL)
                return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
+       // Patch stubroutine.
+       *datap = (uintptr_t) m->stubroutine;
 
-       /* patch stubroutine */
+       // Synchronize data cache.
+       md_dcacheflush((void*) pr->datap, SIZEOF_VOID_P);
 
-       *datap = (intptr_t) m->stubroutine;
+       // Patch back the original code.
+       patcher_patch_code(pr);
 
        return true;
 }
@@ -395,30 +355,23 @@ bool patcher_invokestatic_special(patchref_t *pr)
 
 bool patcher_invokevirtual(patchref_t *pr)
 {
-       uint8_t           *ra;
-       unresolved_method *um;
-       methodinfo        *m;
-
-       ra = (uint8_t *)           pr->mpc;
-       um = (unresolved_method *) pr->ref;
+       uint8_t*           pc = (uint8_t*)           pr->mpc;
+       unresolved_method* um = (unresolved_method*) pr->ref;
 
-       /* get the methodinfo */
+       // Resovlve the method.
+       methodinfo* m = resolve_method_eager(um);
 
-       if (!(m = resolve_method_eager(um)))
+       if (m == NULL)
                return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
-
-       /* if we show disassembly, we have to skip the nop's */
+       // Patch vftbl index.
+       *((int32_t*) (pc + 3 + 3)) = (int32_t) (OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex);
 
-       if (opt_shownops)
-               ra = ra + PATCHER_CALL_SIZE;
+       // Synchronize instruction cache.
+       md_icacheflush(pc + 3 + 3, SIZEOF_VOID_P);
 
-       /* patch vftbl index */
-
-       *((int32_t *) (ra + 3 + 3)) =
-               (int32_t) (OFFSET(vftbl_t, table[0]) +
-                                  sizeof(methodptr) * m->vftblindex);
+       // Patch back the original code.
+       patcher_patch_code(pr);
 
        return true;
 }
@@ -438,37 +391,26 @@ bool patcher_invokevirtual(patchref_t *pr)
 
 bool patcher_invokeinterface(patchref_t *pr)
 {
-       uint8_t           *ra;
-       unresolved_method *um;
-       methodinfo        *m;
-
-       /* get stuff from the stack */
-
-       ra = (uint8_t *)           pr->mpc;
-       um = (unresolved_method *) pr->ref;
+       uint8_t*           pc = (uint8_t*)           pr->mpc;
+       unresolved_method* um = (unresolved_method*) pr->ref;
 
-       /* get the fieldinfo */
+       // Resolve the method.
+       methodinfo* m = resolve_method_eager(um);
 
-       if (!(m = resolve_method_eager(um)))
+       if (m == NULL)
                return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
-
-       /* if we show disassembly, we have to skip the nop's */
-
-       if (opt_shownops)
-               ra = ra + PATCHER_CALL_SIZE;
-
-       /* patch interfacetable index */
+       // Patch interfacetable index.
+       *((int32_t*) (pc + 3 + 3)) = (int32_t) (OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr) * m->clazz->index);
 
-       *((int32_t *) (ra + 3 + 3)) =
-               (int32_t) (OFFSET(vftbl_t, interfacetable[0]) -
-                                  sizeof(methodptr) * m->clazz->index);
+       // Patch method offset.
+       *((int32_t*) (pc + 3 + 7 + 3)) = (int32_t) (sizeof(methodptr) * (m - m->clazz->methods));
 
-       /* patch method offset */
+       // Synchronize instruction cache.
+       md_icacheflush(pc + 3 + 3, SIZEOF_VOID_P + 3 + SIZEOF_VOID_P);
 
-       *((int32_t *) (ra + 3 + 7 + 3)) =
-               (int32_t) (sizeof(methodptr) * (m - m->clazz->methods));
+       // Patch back the original code.
+       patcher_patch_code(pr);
 
        return true;
 }
@@ -489,32 +431,25 @@ bool patcher_invokeinterface(patchref_t *pr)
 
 bool patcher_checkcast_interface(patchref_t *pr)
 {
-       uint8_t           *ra;
-       constant_classref *cr;
-       classinfo         *c;
+       uint8_t*           pc = (uint8_t*)           pr->mpc;
+       constant_classref* cr = (constant_classref*) pr->ref;
 
-       ra = (uint8_t *)           pr->mpc;
-       cr = (constant_classref *) pr->ref;
+       // Resolve the class.
+       classinfo* c = resolve_classref_eager(cr);
 
-       /* get the fieldinfo */
-
-       if (!(c = resolve_classref_eager(cr)))
+       if (c == NULL)
                return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
-
-       /* if we show disassembly, we have to skip the nop's */
-
-       if (opt_shownops)
-               ra = ra + PATCHER_CALL_SIZE;
+       // Patch super class index.
+       *((int32_t*) (pc + 7 + 3)) = c->index;
 
-       /* patch super class index */
+       *((int32_t*) (pc + 7 + 7 + 6 + 8 + 3)) = (int32_t) (OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*));
 
-       *((int32_t *) (ra + 7 + 3)) = c->index;
+       // Synchronize instruction cache.
+       md_icacheflush(pc + 7 + 3, sizeof(int32_t) + 6 + 8 + 3 + sizeof(int32_t));
 
-       *((int32_t *) (ra + 7 + 7 + 6 + 8 + 3)) =
-               (int32_t) (OFFSET(vftbl_t, interfacetable[0]) -
-                                  c->index * sizeof(methodptr*));
+       // Patch back the original code.
+       patcher_patch_code(pr);
 
        return true;
 }
@@ -534,32 +469,25 @@ bool patcher_checkcast_interface(patchref_t *pr)
 
 bool patcher_instanceof_interface(patchref_t *pr)
 {
-       uint8_t           *ra;
-       constant_classref *cr;
-       classinfo         *c;
+       uint8_t*           pc = (uint8_t*)           pr->mpc;
+       constant_classref* cr = (constant_classref*) pr->ref;
 
-       ra = (uint8_t *)           pr->mpc;
-       cr = (constant_classref *) pr->ref;
+       // Resolve the class.
+       classinfo* c = resolve_classref_eager(cr);
 
-       /* get the fieldinfo */
-
-       if (!(c = resolve_classref_eager(cr)))
+       if (c == NULL)
                return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
-
-       /* if we show disassembly, we have to skip the nop's */
-
-       if (opt_shownops)
-               ra = ra + PATCHER_CALL_SIZE;
+       // Patch super class index.
+       *((int32_t*) (pc + 7 + 3)) = c->index;
 
-       /* patch super class index */
+       *((int32_t*) (pc + 7 + 7 + 6 + 3)) = (int32_t) (OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*));
 
-       *((int32_t *) (ra + 7 + 3)) = c->index;
+       // Synchronize instruction cache.
+       md_icacheflush(pc + 7 + 3, sizeof(int32_t) + 6 + 3 + sizeof(int32_t));
 
-       *((int32_t *) (ra + 7 + 7 + 6 + 3)) =
-               (int32_t) (OFFSET(vftbl_t, interfacetable[0]) -
-                                  c->index * sizeof(methodptr*));
+       // Patch back the original code.
+       patcher_patch_code(pr);
 
        return true;
 }
index 5619c9b04087be24fc6b891aa3a27512ba3052b1..14824a49e62a305f34c122b52b9873e24abb0b4e 100644 (file)
@@ -37,7 +37,7 @@
 
 #include "threads/thread.hpp"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/signallocal.h"
 
 #include "vm/jit/asmpart.h"
index 622935cdddca462376cf7f42dcbd268b8aa25c43..cda34a0d183c535256622f0f85e7691375eb2237 100644 (file)
 
 #include "mm/memory.h"
 
-#include "native/native.h"
+#include "native/native.hpp"
 
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
+#include "threads/mutex.hpp"
 
 #include "toolbox/logging.h"
 
 #include "vm/access.h"
-#include "vm/array.h"
+#include "vm/array.hpp"
 #include "vm/class.h"
 #include "vm/classcache.h"
 #include "vm/exceptions.hpp"
 #include "vm/globals.hpp"
-#include "vm/loader.h"
+#include "vm/loader.hpp"
 #include "vm/options.h"
 #include "vm/primitive.hpp"
 #include "vm/rt-timing.h"
@@ -52,6 +53,7 @@
 #include "vm/vm.hpp"
 
 #include "vm/jit/asmpart.h"
+#include "vm/jit/stubs.hpp"
 
 
 /* debugging macros ***********************************************************/
@@ -92,7 +94,7 @@ classinfo *resolve_classref_or_classinfo_eager(classref_or_classinfo cls, bool c
 static s4 interfaceindex;       /* sequential numbering of interfaces         */
 static s4 classvalue;
 
-java_object_t *linker_classrenumber_lock;
+Mutex *linker_classrenumber_mutex;
 
 
 /* private functions **********************************************************/
@@ -121,11 +123,9 @@ void linker_preinit(void)
        interfaceindex = 0;
 
 #if defined(ENABLE_THREADS)
-       /* create the global lock object */
+       /* create the global mutex */
 
-       linker_classrenumber_lock = NEW(java_object_t);
-
-       LOCK_INIT_OBJECT_LOCK(linker_classrenumber_lock);
+       linker_classrenumber_mutex = Mutex_new();
 #endif
 
        /* Link the most basic classes. */
@@ -847,7 +847,7 @@ static classinfo *link_class_intern(classinfo *c)
                        m->stubroutine = intrp_createcompilerstub(m);
                else
 #endif
-                       m->stubroutine = codegen_generate_stub_compiler(m);
+                       m->stubroutine = CompilerStub_generate(m);
 #else
                m->stubroutine = intrp_createcompilerstub(m);
 #endif
@@ -1119,7 +1119,7 @@ static arraydescriptor *link_array(classinfo *c)
 
 static void linker_compute_subclasses(classinfo *c)
 {
-       LOCK_MONITOR_ENTER(linker_classrenumber_lock);
+       Mutex_lock(linker_classrenumber_mutex);
 
        if (!(c->flags & ACC_INTERFACE)) {
                c->nextsub = NULL;
@@ -1137,7 +1137,7 @@ static void linker_compute_subclasses(classinfo *c)
 
        linker_compute_class_values(class_java_lang_Object);
 
-       LOCK_MONITOR_EXIT(linker_classrenumber_lock);
+       Mutex_unlock(linker_classrenumber_mutex);
 }
 
 
index a11f80cd00580fa0e54918318864747d9c0ef771..df74bdad750a2427576e9f13b00137d13c21e3b0 100644 (file)
@@ -28,7 +28,6 @@
 
 /* forward typedefs ***********************************************************/
 
-typedef struct _vftbl vftbl_t;
 typedef struct arraydescriptor arraydescriptor;
 typedef struct primitivetypeinfo primitivetypeinfo;
 
@@ -36,80 +35,11 @@ typedef struct primitivetypeinfo primitivetypeinfo;
 #include "config.h"
 #include "vm/types.h"
 
+#include "threads/mutex.hpp"
+
 #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                         */
-};
+#include "vm/vftbl.hpp"
 
 
 /* arraydescriptor *************************************************************
@@ -136,15 +66,23 @@ struct arraydescriptor {
 /* This lock must be taken while renumbering classes or while atomically      */
 /* accessing classes.                                                         */
 
-extern java_object_t *linker_classrenumber_lock;
+extern Mutex *linker_classrenumber_mutex;
 
 
 /* function prototypes ********************************************************/
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 void       linker_preinit(void);
 void       linker_init(void);
 classinfo *link_class(classinfo *c);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* _LINKER_H */
 
 
diff --git a/src/vm/loader.c b/src/vm/loader.c
deleted file mode 100644 (file)
index 218f695..0000000
+++ /dev/null
@@ -1,2226 +0,0 @@
-/* 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:
- */
diff --git a/src/vm/loader.cpp b/src/vm/loader.cpp
new file mode 100644 (file)
index 0000000..aa0650e
--- /dev/null
@@ -0,0 +1,2218 @@
+/* src/vm/loader.cpp - 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/dumpmemory.hpp"
+#include "mm/memory.h"
+
+#include "native/llni.h"
+
+#include "threads/mutex.hpp"
+
+#include "toolbox/hashtable.h"
+#include "toolbox/logging.h"
+
+#include "vm/jit/builtin.hpp"
+#include "vm/classcache.h"
+#include "vm/exceptions.hpp"
+#include "vm/field.hpp"
+#include "vm/global.h"
+#include "vm/globals.hpp"
+#include "vm/linker.h"
+#include "vm/loader.hpp"
+#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.hpp"
+#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
+
+#include "vm/jit/stubs.hpp"
+
+#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)
+{
+       TRACESUBSYSTEMINITIALIZATION("loader_preinit");
+
+#if defined(ENABLE_THREADS)
+       /* Initialize the monitor pointer for zip/jar file locking. */
+
+       for (List<list_classpath_entry*>::iterator it = list_classpath_entries->begin(); it != list_classpath_entries->end(); it++) {
+               list_classpath_entry* lce = *it;
+
+               if (lce->type == CLASSPATH_ARCHIVE)
+                       lce->mutex = new Mutex();
+       }
+#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::get_current()->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::get_current()->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;
+
+       hashtable_classloader->mutex->lock();
+
+       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_entry*) 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_entry*) hashtable_classloader->ptr[slot];
+               hashtable_classloader->ptr[slot] = cle;
+
+               /* update number of entries */
+
+               hashtable_classloader->entries++;
+       }
+
+       hashtable_classloader->mutex->unlock();
+
+#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_entry*) 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)
+{
+#if defined(ENABLE_ZLIB)
+       hashtable               *ht;
+       hashtable_zipfile_entry *htzfe;
+       utf                     *u;
+#endif
+
+       for (List<list_classpath_entry*>::iterator it = list_classpath_entries->begin(); it != list_classpath_entries->end(); it++) {
+               list_classpath_entry* lce = *it;
+
+#if defined(ENABLE_ZLIB)
+               if (lce->type == CLASSPATH_ARCHIVE) {
+                       /* get the classes hashtable */
+
+                       ht = lce->htclasses;
+
+                       for (uint32_t 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:
+#warning Use list.
+                       nfc = (forward_class*) DumpMemory::allocate(sizeof(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:
+#warning Use list.
+                       nfs = (forward_string*) DumpMemory::allocate(sizeof(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:
+#warning Use list.
+                       nfn = (forward_nameandtype*) DumpMemory::allocate(sizeof(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:
+#warning Use list.
+                       nff = (forward_fieldmethint*) DumpMemory::allocate(sizeof(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 = (utf*) 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 = (utf*) 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 = (utf*) class_getconstant(c,
+                                                                                       forward_nameandtypes->name_index,
+                                                                                       CONSTANT_Utf8);
+               if (!cn->name)
+                       return false;
+
+               cn->descriptor = (utf*) 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 = (constant_nameandtype*) 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);
+
+       *signature = (utf*) class_getconstant(c, signature_index, CONSTANT_Utf8);
+
+       if (*signature == NULL)
+               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 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
+
+       // Create new dump memory area.
+       DumpMemoryArea dma;
+
+       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 = (utf**) DumpMemory::allocate(sizeof(utf*) * c->interfacescount);
+
+       for (int32_t 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 (int32_t 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 (int32_t 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 = (u1*) 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 (int32_t 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 (int32_t 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 (int32_t 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 (int32_t 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 (int32_t 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 (int32_t 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 (int32_t 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 */
+               int32_t len;
+               int32_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 (int32_t 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 (int32_t 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;
+
+       /* 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
+
+       /* Class is currently loading. */
+
+       c->state |= CLASS_LOADING;
+
+       /* Parse the classbuffer. */
+
+       result = load_class_from_classbuffer_intern(cb);
+
+       /* 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);
+
+       /* ATTENTION: if you delete the ACC_NATIVE below, set
+          clone->maxlocals=1 (interpreter related) */
+
+       clone->mutex      = new Mutex();
+       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 = NativeStub::generate(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:
+ */
diff --git a/src/vm/loader.h b/src/vm/loader.h
deleted file mode 100644 (file)
index 3b2c353..0000000
+++ /dev/null
@@ -1,182 +0,0 @@
-/* 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:
- */
diff --git a/src/vm/loader.hpp b/src/vm/loader.hpp
new file mode 100644 (file)
index 0000000..bbf5eeb
--- /dev/null
@@ -0,0 +1,191 @@
+/* src/vm/loader.hpp - 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_HPP
+#define _LOADER_HPP
+
+/* 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 ********************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+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);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _LOADER_HPP
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
index 08171f1d9ded027446a89e163e0caf3cb26db619..15b808a9992cc3d93fb8f92bfbdf246622aab0ab 100644 (file)
 
 #include "native/llni.h"
 
-#include "threads/lock-common.h"
+#include "threads/mutex.hpp"
 
-#include "vm/array.h"
-#include "vm/builtin.h"
+#include "vm/array.hpp"
+#include "vm/jit/builtin.hpp"
 #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/loader.hpp"
 #include "vm/method.h"
 #include "vm/options.h"
 #include "vm/resolve.h"
-#include "vm/suck.h"
+#include "vm/suck.hpp"
 #include "vm/utf8.h"
 #include "vm/vm.hpp"
 
-#include "vm/jit/code.h"
+#include "vm/jit/code.hpp"
 #include "vm/jit/methodheader.h"
+#include "vm/jit/stubs.hpp"
 
 
 #if !defined(NDEBUG) && defined(ENABLE_INLINING)
@@ -143,7 +144,7 @@ bool method_load(classbuffer *cb, methodinfo *m, descriptor_pool *descpool)
 
        c = cb->clazz;
 
-       LOCK_INIT_OBJECT_LOCK(&(m->header));
+       m->mutex = Mutex_new();
 
 #if defined(ENABLE_STATISTICS)
        if (opt_stat)
@@ -527,6 +528,9 @@ bool method_load(classbuffer *cb, methodinfo *m, descriptor_pool *descpool)
 
 void method_free(methodinfo *m)
 {
+       if (m->mutex)
+               Mutex_delete(m->mutex);
+
        if (m->jcode)
                MFREE(m->jcode, u1, m->jcodelength);
 
@@ -537,10 +541,10 @@ void method_free(methodinfo *m)
 
        if (m->stubroutine) {
                if (m->flags & ACC_NATIVE) {
-                       removenativestub(m->stubroutine);
-
-               else {
-                       removecompilerstub(m->stubroutine);
+                       NativeStub_remove(m->stubroutine);
+               }
+               else {
+                       CompilerStub_remove(m->stubroutine);
                }
        }
 }
@@ -586,8 +590,8 @@ methodinfo *method_new_builtin(builtintable_entry *bte)
        /* initialize methodinfo structure */
 
        MZERO(m, methodinfo, 1);
-       LOCK_INIT_OBJECT_LOCK(&(m->header));
-
+       
+       m->mutex      = Mutex_new();
        m->flags      = ACC_METHOD_BUILTIN;
        m->parseddesc = bte->md;
        m->name       = bte->name;
index 076b25a5ca79cf02561e4356042b92200fe51fb1..994a6c22916811060068ba0a748c438e70920802 100644 (file)
 #ifndef _METHOD_H
 #define _METHOD_H
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /* forward typedefs ***********************************************************/
 
 typedef struct methodinfo          methodinfo; 
@@ -42,11 +38,13 @@ typedef struct codeinfo            codeinfo;
 #include "config.h"
 #include "vm/types.h"
 
-#include "vm/builtin.h"
+#include "threads/mutex.hpp"
+
+#include "vm/jit/builtin.hpp"
 #include "vm/descriptor.h"
 #include "vm/global.h"
 #include "vm/linker.h"
-#include "vm/loader.h"
+#include "vm/loader.hpp"
 #include "vm/references.h"
 
 #if defined(ENABLE_JAVASE)
@@ -65,7 +63,7 @@ typedef struct codeinfo            codeinfo;
 /* methodinfo *****************************************************************/
 
 struct methodinfo {                 /* method structure                       */
-       java_object_t header;           /* we need this in jit's monitorenter     */
+       Mutex        *mutex;            /* we need this in jit's locking          */
        s4            flags;            /* ACC flags                              */
        utf          *name;             /* name of method                         */
        utf          *descriptor;       /* JavaVM descriptor string of method     */
@@ -165,6 +163,10 @@ struct lineinfo {
 extern methodinfo *method_java_lang_reflect_Method_invoke;
 
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /* inline functions ***********************************************************/
 
 inline static bool method_is_builtin(methodinfo* m)
index 0366ebefe7cf2f54177b8a24f47aa611888af726..f1c085114dcf6849332904033e4482f4775d992f 100644 (file)
@@ -32,8 +32,6 @@
 
 #include "mm/memory.h"
 
-#include "native/jni.h"
-
 #include "vm/options.h"
 #include "vm/os.hpp"
 #include "vm/vm.hpp"
@@ -85,12 +83,10 @@ 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           */
index 28fdf1d6da0090996f3ef93f336ce1c6b4a9a32a..0861d0e6f728bff5c5c8dc4e897483d5b928e4ca 100644 (file)
@@ -36,7 +36,7 @@ extern "C" {
 
 #include "vm/types.h"
 
-#include "native/jni.h"
+#include "native/jni.hpp"
 
 #include "vm/global.h"
 
@@ -109,12 +109,10 @@ 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;
index 0c920a86798c185cee2a7b6bfd72a8fbb707eb2f..296834f161c4aa0851e8371841a1053cdab50b8b 100644 (file)
@@ -2,6 +2,7 @@
 
    Copyright (C) 2007, 2008
    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+   Copyright (C) 2008 Theobroma Systems Ltd.
 
    This file is part of CACAO.
 
 #include "vm/vm.hpp"
 
 
+/**
+ * Prints an error message and aborts the VM.
+ *
+ * @param text Error message to print.
+ */
+void os::abort(const char* text, ...)
+{
+       va_list ap;
+
+       // Print the log message.
+       log_start();
+
+       va_start(ap, text);
+       log_vprint(text, ap);
+       va_end(ap);
+
+       log_finish();
+
+       // Print a backtrace.
+       os::print_backtrace();
+
+       // Now abort the VM.
+       os::abort();
+}
+
+
+/**
+ * Prints an error message, appends ":" plus the strerror-message of
+ * errnum and aborts the VM.
+ *
+ * @param errnum Error number.
+ * @param text   Error message to print.
+ */
+void os::abort_errnum(int errnum, const char* text, ...)
+{
+       va_list ap;
+
+       // Print the log message.
+       log_start();
+
+       va_start(ap, text);
+       log_vprint(text, ap);
+       va_end(ap);
+
+       // Print the strerror-message of errnum.
+       log_print(": %s", os::strerror(errnum));
+
+       log_finish();
+
+       // Print a backtrace.
+       os::print_backtrace();
+
+       // Now abort the VM.
+       os::abort();
+}
+
+
+/**
+ * Equal to abort_errnum, but uses errno to get the error number.
+ *
+ * @param text Error message to print.
+ */
+void os::abort_errno(const char* text, ...)
+{
+       va_list ap;
+
+       va_start(ap, text);
+       abort_errnum(errno, text, ap);
+       va_end(ap);
+}
+
+
 /**
  * Maps anonymous memory, even on systems not defining
  * MAP_ANON(YMOUS).
@@ -84,7 +157,7 @@ void* os::mmap_anonymous(void *addr, size_t len, int prot, int flags)
        fd = open("/dev/zero", O_RDONLY, 0);
 
        if (fd == -1)
-               vm_abort("os::mmap_anonymous: open failed: %s", os::strerror(errno));
+               os::abort_errno("os::mmap_anonymous: open failed");
 
        p = mmap(addr, len, prot, flags, fd, 0);
 #endif
@@ -94,12 +167,36 @@ void* os::mmap_anonymous(void *addr, size_t len, int prot, int flags)
 #else
        if (p == (void *) -1)
 #endif
-               vm_abort("os::mmap_anonymous: mmap failed: %s", os::strerror(errno));
+               os::abort_errno("os::mmap_anonymous: mmap failed");
 
        return p;
 }
 
 
+/**
+ * Print a C backtrace.
+ */
+void os::print_backtrace()
+{
+#define BACKTRACE_SIZE 100
+       void** array = new void*[SIZEOF_VOID_P * BACKTRACE_SIZE];
+
+       // Get the backtrace.
+       int size = backtrace(array, BACKTRACE_SIZE);
+
+       // Resolve the symbols.
+       char** strings = backtrace_symbols(array, size);
+
+       log_println("Backtrace (%d stack frames):", size);
+
+       for (int i = 0; i < size; i++)
+               log_println("%s", strings[i]);
+
+       // We have to free the strings.
+       free(strings);
+}
+
+
 /**
  * Returns the number of online processors in the system.
  *
@@ -168,9 +265,7 @@ extern "C" {
 #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); }
index 243ffc06fc5de1e3c9b166dbb71e0005953f4129..6a18dd71ddbda4d06b10735611f669a41a170e99 100644 (file)
@@ -2,6 +2,7 @@
 
    Copyright (C) 2007, 2008
    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+   Copyright (C) 2008 Theobroma Systems Ltd.
 
    This file is part of CACAO.
 
 
 #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. */
+// NOTE: In this file we check for all system headers, because we wrap
+// all system calls into inline functions for better portability.
+
+// Please don't include CACAO headers here as this header should be a
+// very low-level one.
 
 #if defined(HAVE_DIRENT_H)
 # include <dirent.h>
 # include <errno.h>
 #endif
 
+#if defined(HAVE_EXECINFO_H)
+# include <execinfo.h>
+#endif
+
 #if defined(HAVE_FCNTL_H)
 # include <fcntl.h>
 #endif
 # include <signal.h>
 #endif
 
+#if defined(HAVE_STDARG_H)
+# include <stdarg.h>
+#endif
+
 #if defined(HAVE_STDINT_H)
 # include <stdint.h>
 #endif
 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);
+       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 int     backtrace(void** array, int size);
+       static inline char**  backtrace_symbols(void* const* array, int size) throw ();
+       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*   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 int     fprintf(FILE* stream, const char* format, ...);
+       static inline size_t  fread(void* ptr, size_t size, size_t nmemb, FILE* stream);
+       static inline void    free(void* ptr);
+       static inline char*   getenv(const char* name);
+       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 ssize_t readlink(const char* path, char* buf, size_t bufsiz);
+       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);
 #if defined(__SOLARIS__)
-       static inline int    str2sig(const char* str, int* signum);
-#endif
-       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 inline int     str2sig(const char* str, int* signum);
+#endif
+       static inline char*   strcat(char* dest, const char* src);
+       static inline int     strcmp(const char* s1, const char* s2);
+       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);
+
+       // Convenience functions.
+       static void  abort(const char* text, ...);
+       static void  abort_errnum(int errnum, const char* text, ...);
+       static void  abort_errno(const char* text, ...);
        static void* mmap_anonymous(void *addr, size_t len, int prot, int flags);
-       static int   processors_online(void);
+       static void  print_backtrace();
+       static int   processors_online();
 };
 
 
@@ -182,6 +205,26 @@ inline int os::atoi(const char* nptr)
 #endif
 }
 
+inline int os::backtrace(void** array, int size)
+{
+#if defined(HAVE_BACKTRACE)
+       return ::backtrace(array, size);
+#else
+       fprintf(stderr, "os::backtrace: Not available.");
+       return 0;
+#endif
+}
+
+inline char** os::backtrace_symbols(void* const* array, int size) throw ()
+{
+#if defined(HAVE_BACKTRACE_SYMBOLS)
+       return ::backtrace_symbols(array, size);
+#else
+       fprintf(stderr, "os::backtrace_symbols: Not available.");
+       return NULL;
+#endif
+}
+
 inline void* os::calloc(size_t nmemb, size_t size)
 {
 #if defined(HAVE_CALLOC)
@@ -232,7 +275,9 @@ inline int os::dlclose(void* handle)
 inline char* os::dlerror(void)
 {
 #if defined(HAVE_DLERROR)
-       return ::dlerror();
+       // At least FreeBSD defines dlerror() to return a const char*, so
+       // we simply cast it.
+       return (char*) ::dlerror();
 #else
 # error dlerror not available
 #endif
@@ -274,6 +319,19 @@ inline FILE* os::fopen(const char* path, const char* mode)
 #endif
 }
 
+inline int os::fprintf(FILE* stream, const char* format, ...)
+{
+#if defined(HAVE_FPRINTF)
+       va_list ap;
+       va_start(ap, format);
+       int result = ::fprintf(stream, format, ap);
+       va_end(ap);
+       return result;
+#else
+# error fprintf not available
+#endif
+}
+
 inline size_t os::fread(void* ptr, size_t size, size_t nmemb, FILE* stream)
 {
 #if defined(HAVE_FREAD)
@@ -319,6 +377,15 @@ inline static int system_ftruncate(int fd, off_t length)
 #endif
 }
 
+inline char* os::getenv(const char* name)
+{
+#if defined(HAVE_GETENV)
+       return ::getenv(name);
+#else
+# error getenv not available
+#endif
+}
+
 inline int os::gethostname(char* name, size_t len)
 {
 #if defined(HAVE_GETHOSTNAME)
@@ -427,6 +494,15 @@ inline static ssize_t system_read(int fd, void *buf, size_t count)
 #endif
 }
 
+inline ssize_t os::readlink(const char* path, char* buf, size_t bufsiz)
+{
+#if defined(HAVE_READLINK)
+       return ::readlink(path, buf, bufsiz);
+#else
+# error readlink not available
+#endif
+}
+
 inline static void *system_realloc(void *ptr, size_t size)
 {
 #if defined(HAVE_REALLOC)
@@ -516,6 +592,15 @@ inline char* os::strcat(char* dest, const char* src)
 #endif
 }
 
+inline int os::strcmp(const char* s1, const char* s2)
+{
+#if defined(HAVE_STRCMP)
+       return ::strcmp(s1, s2);
+#else
+# error strcmp not available
+#endif
+}
+
 inline char* os::strcpy(char* dest, const char* src)
 {
 #if defined(HAVE_STRCPY)
@@ -570,9 +655,7 @@ 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);
index 5e5d3b2004ef910b911f256ce371dac47813d0a0..a112aca2f7d95045bea1a33d1acd41fabc8d4a81 100644 (file)
 
 #include <stdint.h>
 
-#include "toolbox/list.h"
-
 #include "mm/memory.h"
 
-#include "native/jni.h"
-
 #include "vm/options.h"
 #include "vm/package.hpp"
 #include "vm/string.hpp"
 #include "vm/utf8.h"
 
 
-/* internal property structure ************************************************/
-
-typedef struct list_package_entry_t list_package_entry_t;
-
-struct list_package_entry_t {
-/*     java_string_t *packagename; */
-       utf           *packagename;
-       listnode_t     linkage;
-};
-
+// Package list.
 
-/* global variables ***********************************************************/
-
-static list_t *list_package = NULL;
-
-
-/**
- * Initialize the package list.
- */
-void Package::initialize(void)
-{
-       TRACESUBSYSTEMINITIALIZATION("package_init");
-
-       /* create the properties list */
-
-       list_package = list_create(OFFSET(list_package_entry_t, linkage));
-}
+std::set<utf*> Package::_packages;
 
 
 /**
@@ -73,23 +45,11 @@ void Package::initialize(void)
  *
  * @param packagename Package name as Java string.
  */
-/* void package_add(java_handle_t *packagename) */
-void Package::add(utf *packagename)
+void Package::add(utf* packagename)
 {
-/*     java_string_t        *s; */
-       list_package_entry_t *lpe;
-
-       /* Intern the Java string to get a unique address. */
-
+       // Intern the Java string to get a unique address.
 /*     s = javastring_intern(packagename); */
 
-       /* Check if the package is already stored. */
-
-       if (Package::find(packagename) != NULL)
-               return;
-
-       /* Add the package. */
-
 #if !defined(NDEBUG)
        if (opt_DebugPackage) {
                log_start();
@@ -100,11 +60,8 @@ void Package::add(utf *packagename)
        }
 #endif
 
-       lpe = NEW(list_package_entry_t);
-
-       lpe->packagename = packagename;
-
-       list_add_last(list_package, lpe);
+       // Add the package name.
+       _packages.insert(packagename);
 }
 
 
@@ -115,39 +72,14 @@ void Package::add(utf *packagename)
  *
  * @return Package name as Java string.
  */
-/* java_handle_t *package_find(java_handle_t *packagename) */
-utf* Package::find(utf *packagename)
+utf* Package::find(utf* packagename)
 {
-/*     java_string_t        *s; */
-       list_t               *l;
-       list_package_entry_t *lpe;
-
-       /* Intern the Java string to get a unique address. */
-
-/*     s = javastring_intern(packagename); */
-
-       /* For convenience. */
-
-       l = list_package;
-
-       for (lpe = (list_package_entry_t*) list_first(l); lpe != NULL; lpe = (list_package_entry_t*) list_next(l, lpe)) {
-/*             if (lpe->packagename == s) */
-               if (lpe->packagename == packagename)
-                       return lpe->packagename;
-       }
-
-       return NULL;
-}
-
-
-/* Legacy C interface *********************************************************/
-
-extern "C" {
+       std::set<utf*>::iterator it = _packages.find(packagename);
 
-void Package_initialize(void) { Package::initialize(); }
-void Package_add(utf* packagename) { Package::add(packagename); }
-utf* Package_find(utf *packagename) { return Package::find(packagename); }
+       if (it == _packages.end())
+               return NULL;
 
+       return *it;
 }
 
 
index 38b129a6dbb598159115e623fa0b87cc688bd012..7e7669bd0f0a01158e1922f3b31b519e19c5795f 100644 (file)
 
 #include "config.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #include <stdint.h>
 
-#include "native/jni.h"
-
-#include "vm/global.h"
-
-#ifdef __cplusplus
-}
-#endif
+#include <set>
 
+#include "vm/utf8.h"
 
-#ifdef __cplusplus
 
 /**
  *
  */
 class Package {
+private:
+       static std::set<utf*> _packages;
+
 public:
-       static void initialize();
-       /* static void add(java_handle_t *packagename); */
-       static void add(utf *packagename);
-       /* static java_handle_t* find(java_handle_t *packagename); */
-       static utf* find(utf *packagename);
+       static void add (utf* packagename);
+       static utf* find(utf* packagename);
 };
 
-#else
-
-/* Legacy C interface *********************************************************/
-
-typedef struct Package Package;
-
-void Package_initialize();
-void Package_add(utf* packagename);
-utf* Package_find(utf* packagename);
-
-#endif
-
-#endif /* _VM_PACKAGE_HPP */
+#endif // _VM_PACKAGE_HPP
 
 
 /*
index 2b1b27a621f915ffd16096a54afa925fa0b7c1be..0a2d42212365b0fa394904783ca18266edd835aa 100644 (file)
 #include <assert.h>
 #include <stdint.h>
 
-#include "native/jni.h"
 #include "native/llni.h"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/class.h"
 #include "vm/global.h"
 #include "vm/globals.hpp"
 #include "vm/javaobjects.hpp"
+#include "vm/options.h"
+#include "vm/os.hpp"
 #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
+};
+
+
+/**
+ * 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::initialize_table()
+{  
+       utf       *name;
+       classinfo *c;
+       utf       *u;
+       classinfo *ac;
+
+       TRACESUBSYSTEMINITIALIZATION("primitive_init");
+
+       /* Load and link primitive-type classes and array-classes. */
+
+       for (int 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 (int 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;
+       }
+}
+
+
+/**
+ * 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::post_initialize_table()
+{
+       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;
+       }
+}
 
 
 /**
@@ -227,7 +412,7 @@ java_handle_t* Primitive::box(int type, imm_union value)
                break;
        default:
                o = NULL;
-               vm_abort("primitive_box: invalid primitive type %d", type);
+               os::abort("Primitive::box: Invalid primitive type %d", type);
        }
 
        return o;
@@ -288,7 +473,7 @@ imm_union Primitive::unbox(java_handle_t *h)
                value.a = h;
                break;
        default:
-               vm_abort("Primitive::unbox: invalid primitive type %d", type);
+               os::abort("Primitive::unbox: Invalid primitive type %d", type);
        }
 
        return value;
@@ -467,14 +652,9 @@ inline double Primitive::unbox_double(java_handle_t *h)
 
 extern "C" {
 
-       classinfo* Primitive_get_class_by_name(utf *name) { return Primitive::get_class_by_name(name); }
+classinfo* Primitive_get_class_by_name(utf *name) { return Primitive::get_class_by_name(name); }
 classinfo* Primitive_get_class_by_type(int type) { return Primitive::get_class_by_type(type); }
-classinfo* Primitive_get_class_by_char(char ch) { return Primitive::get_class_by_char(ch); }
-classinfo* Primitive_get_arrayclass_by_name(utf *name) { return Primitive::get_arrayclass_by_name(name); }
 classinfo* Primitive_get_arrayclass_by_type(int type) { return Primitive::get_arrayclass_by_type(type); }
-int Primitive_get_type_by_wrapperclass(classinfo *c) { return Primitive::get_type_by_wrapperclass(c); }
-java_handle_t* Primitive_box(int type, imm_union value) { return Primitive::box(type, value); }
-imm_union Primitive_unbox(java_handle_t *h) { return Primitive::unbox(h); }
 }
 
 
index d99883d8c041ec0ab11c60c271005163799cf90b..3697b321ccbdbd0135e9bb23454c76a2ec020523 100644 (file)
@@ -40,6 +40,9 @@
 
 class Primitive {
 public:
+       static void initialize_table();
+       static void post_initialize_table();
+
        static classinfo*     get_class_by_name(utf *name);
        static classinfo*     get_class_by_type(int type);
        static classinfo*     get_class_by_char(char ch);
@@ -100,14 +103,14 @@ public:
 /* primitivetypeinfo **********************************************************/
 
 struct primitivetypeinfo {
-       char      *cname;                    /* char name of primitive class      */
-       utf       *name;                     /* name of primitive class           */
-       classinfo *class_wrap;               /* class for wrapping primitive type */
-       classinfo *class_primitive;          /* primitive class                   */
-       char      *wrapname;                 /* name of class for wrapping        */
-       char       typesig;                  /* one character type signature      */
-       char      *arrayname;                /* name of primitive array class     */
-       classinfo *arrayclass;               /* primitive array class             */
+       const char* cname;                   /* char name of primitive class      */
+       utf*        name;                    /* name of primitive class           */
+       classinfo*  class_wrap;              /* class for wrapping primitive type */
+       classinfo*  class_primitive;         /* primitive class                   */
+       const char* wrapname;                /* name of class for wrapping        */
+       const char  typesig;                 /* one character type signature      */
+       const char* arrayname;               /* name of primitive array class     */
+       classinfo*  arrayclass;              /* primitive array class             */
 };
 
 
@@ -126,15 +129,7 @@ void       primitive_postinit(void);
 // Legacy C interface.
 classinfo *Primitive_get_class_by_name(utf *name);
 classinfo *Primitive_get_class_by_type(int type);
-classinfo *Primitive_get_class_by_char(char ch);
-
-classinfo *Primitive_get_arrayclass_by_name(utf *name);
 classinfo *Primitive_get_arrayclass_by_type(int type);
-
-int        Primitive_get_type_by_wrapperclass(classinfo *c);
-
-java_handle_t *Primitive_box(int type, imm_union value);
-imm_union      Primitive_unbox(java_handle_t *h);
 #endif
 
 #endif // _PRIMITIVE_HPP
diff --git a/src/vm/primitivecore.c b/src/vm/primitivecore.c
deleted file mode 100644 (file)
index 0444bf8..0000000
+++ /dev/null
@@ -1,244 +0,0 @@
-/* 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:
- */
diff --git a/src/vm/properties.c b/src/vm/properties.c
deleted file mode 100644 (file)
index 3309007..0000000
+++ /dev/null
@@ -1,752 +0,0 @@
-/* src/vm/properties.c - handling commandline properties
-
-   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 <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <unistd.h>
-#include <sys/utsname.h>
-
-#include "mm/memory.h"
-
-#include "native/jni.h"
-#include "native/llni.h"
-
-#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"
-
-
-/* internal property structure ************************************************/
-
-typedef struct list_properties_entry_t list_properties_entry_t;
-
-struct list_properties_entry_t {
-       const char* key;
-       const char* value;
-       listnode_t  linkage;
-};
-
-
-/* global variables ***********************************************************/
-
-static list_t *list_properties = NULL;
-
-
-/* properties_init *************************************************************
-
-   Initialize the properties list and fill the list with default
-   values.
-
-*******************************************************************************/
-
-void properties_init(void)
-{
-       TRACESUBSYSTEMINITIALIZATION("properties_init");
-
-       list_properties = list_create(OFFSET(list_properties_entry_t, linkage));
-}
-
-
-/* properties_set **************************************************************
-
-   Fill the properties list with default values.
-
-*******************************************************************************/
-
-void properties_set(void)
-{
-       int             len;
-       char           *p;
-
-       char           *java_home;
-       char           *boot_class_path;
-
-#if defined(ENABLE_JAVASE)
-       char           *class_path;
-       char           *boot_library_path;
-       char           *extdirs;
-       char           *endorseddirs;
-
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-       char           *cwd;
-       char           *env_user;
-       char           *env_home;
-       char           *env_lang;
-       char           *lang;
-       char           *country;
-       struct utsname *utsnamebuf;
-
-       char           *java_library_path;
-# endif
-#endif
-
-#if defined(ENABLE_JRE_LAYOUT)
-       /* SUN also uses a buffer of 4096-bytes (strace is your friend). */
-
-       p = MNEW(char, 4096);
-
-       if (readlink("/proc/self/exe", p, 4095) == -1)
-               vm_abort("properties_set: readlink failed: %s\n", strerror(errno));
-
-       /* We have a path like:
-
-          /path/to/executable/bin/java
-
-          or
-          
-          /path/to/executeable/jre/bin/java
-
-          Now let's strip two levels. */
-
-       p = os_dirname(p);
-       p = os_dirname(p);
-
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-
-       /* Set java.home. */
-
-       java_home = strdup(p);
-
-       /* Set the path to Java core native libraries. */
-
-       len = strlen(java_home) + strlen("/lib/classpath") + strlen("0");
-
-       boot_library_path = MNEW(char, len);
-
-       strcpy(boot_library_path, java_home);
-       strcat(boot_library_path, "/lib/classpath");
-
-# elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-
-       /* Find correct java.home.  We check if there is a JRE
-          co-located. */
-
-       /* NOTE: We use the server VM here as it should be available on
-          all architectures. */
-
-       len =
-               strlen(p) +
-               strlen("/jre/lib/"JAVA_ARCH"/server/libjvm.so") +
-               strlen("0");
-
-       java_home = MNEW(char, len);
-
-       strcpy(java_home, p);
-       strcat(java_home, "/jre/lib/"JAVA_ARCH"/server/libjvm.so");
-
-       /* Check if that libjvm.so exists. */
-
-       if (os_access(java_home, F_OK) == 0) {
-               /* Yes, we add /jre to java.home. */
-
-               strcpy(java_home, p);
-               strcat(java_home, "/jre");
-       }
-       else {
-               /* No, java.home is parent directory. */
-
-               strcpy(java_home, p);
-       }
-
-       /* Set the path to Java core native libraries. */
-
-       len = strlen(java_home) + strlen("/lib/"JAVA_ARCH) + strlen("0");
-
-       boot_library_path = MNEW(char, len);
-
-       strcpy(boot_library_path, java_home);
-       strcat(boot_library_path, "/lib/"JAVA_ARCH);
-
-# else
-#  error unknown classpath configuration
-# endif
-
-       /* Free path. */
-
-       MFREE(p, char, len);
-
-#else
-       java_home         = CACAO_PREFIX;
-
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-
-       boot_library_path = JAVA_RUNTIME_LIBRARY_LIBDIR"/classpath";
-
-# elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-
-       boot_library_path = JAVA_RUNTIME_LIBRARY_LIBDIR;
-
-# elif defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
-
-       /* No boot_library_path required. */
-
-# else
-#  error unknown classpath configuration
-# endif
-#endif
-
-       properties_add("java.home", java_home);
-
-       /* Set the bootclasspath. */
-
-       p = getenv("BOOTCLASSPATH");
-
-       if (p != NULL) {
-               boot_class_path = MNEW(char, strlen(p) + strlen("0"));
-               strcpy(boot_class_path, p);
-       }
-       else {
-#if defined(ENABLE_JRE_LAYOUT)
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-
-               len =
-                       strlen(java_home) + strlen("/share/cacao/vm.zip:") +
-                       strlen(java_home) + strlen("/share/classpath/glibj.zip") +
-                       strlen("0");
-
-               boot_class_path = MNEW(char, len);
-
-               strcpy(boot_class_path, java_home);
-               strcat(boot_class_path, "/share/cacao/vm.zip");
-               strcat(boot_class_path, ":");
-               strcat(boot_class_path, java_home);
-               strcat(boot_class_path, "/share/classpath/glibj.zip");
-
-# elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-
-               /* This is the bootclasspath taken from HotSpot (see
-                  hotspot/src/share/vm/runtime/os.cpp
-                  (os::set_boot_path)). */
-
-               len =
-                       strlen(java_home) + strlen("/lib/resources.jar:") +
-                       strlen(java_home) + strlen("/lib/rt.jar:") +
-                       strlen(java_home) + strlen("/lib/sunrsasign.jar:") +
-                       strlen(java_home) + strlen("/lib/jsse.jar:") +
-                       strlen(java_home) + strlen("/lib/jce.jar:") +
-                       strlen(java_home) + strlen("/lib/charsets.jar:") +
-                       strlen(java_home) + strlen("/classes") +
-                       strlen("0");
-
-               boot_class_path = MNEW(char, len);
-
-               strcpy(boot_class_path, java_home);
-               strcat(boot_class_path, "/lib/resources.jar:");
-               strcat(boot_class_path, java_home);
-               strcat(boot_class_path, "/lib/rt.jar:");
-               strcat(boot_class_path, java_home);
-               strcat(boot_class_path, "/lib/sunrsasign.jar:");
-               strcat(boot_class_path, java_home);
-               strcat(boot_class_path, "/lib/jsse.jar:");
-               strcat(boot_class_path, java_home);
-               strcat(boot_class_path, "/lib/jce.jar:");
-               strcat(boot_class_path, java_home);
-               strcat(boot_class_path, "/lib/charsets.jar:");
-               strcat(boot_class_path, java_home);
-               strcat(boot_class_path, "/classes");
-
-# else
-#  error unknown classpath configuration
-# endif
-#else
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-
-               len =
-                       strlen(CACAO_VM_ZIP) +
-                       strlen(":") +
-                       strlen(JAVA_RUNTIME_LIBRARY_CLASSES) +
-                       strlen("0");
-
-               boot_class_path = MNEW(char, len);
-
-               strcpy(boot_class_path, CACAO_VM_ZIP);
-               strcat(boot_class_path, ":");
-               strcat(boot_class_path, JAVA_RUNTIME_LIBRARY_CLASSES);
-
-# elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-
-               /* This is the bootclasspath taken from HotSpot (see
-                  hotspot/src/share/vm/runtime/os.cpp
-                  (os::set_boot_path)). */
-
-               len =
-                       strlen(JAVA_RUNTIME_LIBRARY_PREFIX"/lib/resources.jar:") +
-                       strlen(JAVA_RUNTIME_LIBRARY_PREFIX"/lib/rt.jar:") +
-                       strlen(JAVA_RUNTIME_LIBRARY_PREFIX"/lib/sunrsasign.jar:") +
-                       strlen(JAVA_RUNTIME_LIBRARY_PREFIX"/lib/jsse.jar:") +
-                       strlen(JAVA_RUNTIME_LIBRARY_PREFIX"/lib/jce.jar:") +
-                       strlen(JAVA_RUNTIME_LIBRARY_PREFIX"/lib/charsets.jar:") +
-                       strlen(JAVA_RUNTIME_LIBRARY_PREFIX"/classes") +
-                       strlen("0");
-
-               boot_class_path = MNEW(char, len);
-
-               strcpy(boot_class_path, JAVA_RUNTIME_LIBRARY_PREFIX"/lib/resources.jar:");
-               strcat(boot_class_path, JAVA_RUNTIME_LIBRARY_PREFIX"/lib/rt.jar:");
-               strcat(boot_class_path, JAVA_RUNTIME_LIBRARY_PREFIX"/lib/sunrsasign.jar:");
-               strcat(boot_class_path, JAVA_RUNTIME_LIBRARY_PREFIX"/lib/jsse.jar:");
-               strcat(boot_class_path, JAVA_RUNTIME_LIBRARY_PREFIX"/lib/jce.jar:");
-               strcat(boot_class_path, JAVA_RUNTIME_LIBRARY_PREFIX"/lib/charsets.jar:");
-               strcat(boot_class_path, JAVA_RUNTIME_LIBRARY_PREFIX"/classes");
-
-# elif defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
-
-               len =
-                       strlen(JAVA_RUNTIME_LIBRARY_CLASSES) +
-                       strlen("0");
-
-               boot_class_path = MNEW(char, len);
-
-               strcpy(boot_class_path, JAVA_RUNTIME_LIBRARY_CLASSES);
-
-# else
-#  error unknown classpath configuration
-# endif
-#endif
-       }
-
-       properties_add("sun.boot.class.path", boot_class_path);
-       properties_add("java.boot.class.path", boot_class_path);
-
-#if defined(ENABLE_JAVASE)
-
-       /* Set the classpath. */
-
-       p = getenv("CLASSPATH");
-
-       if (p != NULL) {
-               class_path = MNEW(char, strlen(p) + strlen("0"));
-               strcpy(class_path, p);
-       }
-       else {
-               class_path = MNEW(char, strlen(".") + strlen("0"));
-               strcpy(class_path, ".");
-       }
-
-       properties_add("java.class.path", class_path);
-
-       /* Add java.vm properties. */
-
-       properties_add("java.vm.specification.version", "1.0");
-       properties_add("java.vm.specification.vendor", "Sun Microsystems Inc.");
-       properties_add("java.vm.specification.name", "Java Virtual Machine Specification");
-       properties_add("java.vm.version", VERSION);
-       properties_add("java.vm.vendor", "CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO");
-       properties_add("java.vm.name", "CACAO");
-
-# if defined(ENABLE_INTRP)
-       if (opt_intrp) {
-               /* XXX We don't support java.lang.Compiler */
-/*             properties_add("java.compiler", "cacao.intrp"); */
-               properties_add("java.vm.info", "interpreted mode");
-       }
-       else
-# endif
-       {
-               /* XXX We don't support java.lang.Compiler */
-/*             properties_add("java.compiler", "cacao.jit"); */
-               properties_add("java.vm.info", "JIT mode");
-       }
-
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-
-       /* Get properties from system. */
-
-       cwd      = _Jv_getcwd();
-
-       env_user = getenv("USER");
-       env_home = getenv("HOME");
-       env_lang = getenv("LANG");
-
-       utsnamebuf = NEW(struct utsname);
-
-       uname(utsnamebuf);
-
-       properties_add("java.runtime.version", VERSION);
-       properties_add("java.runtime.name", "CACAO");
-
-       properties_add("java.specification.version", "1.5");
-       properties_add("java.specification.vendor", "Sun Microsystems Inc.");
-       properties_add("java.specification.name", "Java Platform API Specification");
-
-       properties_add("java.version", JAVA_VERSION);
-       properties_add("java.vendor", "GNU Classpath");
-       properties_add("java.vendor.url", "http://www.gnu.org/software/classpath/");
-
-       properties_add("java.class.version", CLASS_VERSION);
-
-       properties_add("gnu.classpath.boot.library.path", boot_library_path);
-
-       /* Get and set java.library.path. */
-
-       java_library_path = getenv("LD_LIBRARY_PATH");
-
-       if (java_library_path == NULL)
-               java_library_path = "";
-
-       properties_add("java.library.path", java_library_path);
-
-       properties_add("java.io.tmpdir", "/tmp");
-
-#  if defined(ENABLE_INTRP)
-       if (opt_intrp) {
-               properties_add("gnu.java.compiler.name", "cacao.intrp");
-       }
-       else
-#  endif
-       {
-               properties_add("gnu.java.compiler.name", "cacao.jit");
-       }
-
-       /* Set the java.ext.dirs property. */
-
-       len = strlen(java_home) + strlen("/jre/lib/ext") + strlen("0");
-
-       extdirs = MNEW(char, len);
-
-       sprintf(extdirs, "%s/jre/lib/ext", java_home);
-
-       properties_add("java.ext.dirs", extdirs);
-
-       /* Set the java.ext.endorsed property. */
-
-       len = strlen(java_home) + strlen("/jre/lib/endorsed") + strlen("0");
-
-       endorseddirs = MNEW(char, len);
-
-       sprintf(endorseddirs, "%s/jre/lib/endorsed", java_home);
-
-       properties_add("java.endorsed.dirs", endorseddirs);
-
-#  if defined(DISABLE_GC)
-       /* When we disable the GC, we mmap the whole heap to a specific
-          address, so we can compare call traces. For this reason we have
-          to add the same properties on different machines, otherwise
-          more memory may be allocated (e.g. strlen("i386")
-          vs. strlen("alpha"). */
-
-       properties_add("os.arch", "unknown");
-       properties_add("os.name", "unknown");
-       properties_add("os.version", "unknown");
-#  else
-       properties_add("os.arch", JAVA_ARCH);
-       properties_add("os.name", utsnamebuf->sysname);
-       properties_add("os.version", utsnamebuf->release);
-#  endif
-
-#  if WORDS_BIGENDIAN == 1
-       properties_add("gnu.cpu.endian", "big");
-#  else
-       properties_add("gnu.cpu.endian", "little");
-#  endif
-
-       properties_add("file.separator", "/");
-       properties_add("path.separator", ":");
-       properties_add("line.separator", "\n");
-
-       properties_add("user.name", env_user ? env_user : "null");
-       properties_add("user.home", env_home ? env_home : "null");
-       properties_add("user.dir", cwd ? cwd : "null");
-
-       /* get locale */
-
-       if (env_lang != NULL) {
-               /* get the local stuff from the environment */
-
-               if (strlen(env_lang) <= 2) {
-                       properties_add("user.language", env_lang);
-               }
-               else {
-                       if ((env_lang[2] == '_') && (strlen(env_lang) >= 5)) {
-                               lang = MNEW(char, 3);
-                               strncpy(lang, (char *) &env_lang[0], 2);
-                               lang[2] = '\0';
-
-                               country = MNEW(char, 3);
-                               strncpy(country, (char *) &env_lang[3], 2);
-                               country[2] = '\0';
-
-                               properties_add("user.language", lang);
-                               properties_add("user.country", country);
-                       }
-               }
-       }
-       else {
-               /* if no default locale was specified, use `en_US' */
-
-               properties_add("user.language", "en");
-               properties_add("user.country", "US");
-       }
-
-# elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-
-       /* Actually this property is set by OpenJDK, but we need it in
-          nativevm_preinit(). */
-
-       properties_add("sun.boot.library.path", boot_library_path);
-
-       /* Set the java.ext.dirs property. */
-
-       len =
-               strlen(java_home) + strlen("/lib/ext") +
-               strlen(":") +
-               strlen("/usr/java/packages/lib/ext") +
-               strlen("0");
-
-       extdirs = MNEW(char, len);
-
-       sprintf(extdirs, "%s/lib/ext:/usr/java/packages/lib/ext", java_home);
-
-       properties_add("java.ext.dirs", extdirs);
-
-       /* Set the java.ext.endorsed property. */
-
-       len = strlen(java_home) + strlen("/lib/endorsed") + strlen("0");
-
-       endorseddirs = MNEW(char, len);
-
-       sprintf(endorseddirs, "%s/lib/endorsed", java_home);
-
-       properties_add("java.endorsed.dirs", endorseddirs);
-
-# else
-
-#  error unknown classpath configuration
-
-# endif
-
-#elif defined(ENABLE_JAVAME_CLDC1_1)
-
-    properties_add("microedition.configuration", "CLDC-1.1");
-    properties_add("microedition.platform", "generic");
-    properties_add("microedition.encoding", "ISO8859_1");
-    properties_add("microedition.profiles", "");
-
-#else
-
-# error unknown Java configuration
-
-#endif
-}
-
-
-/* properties_add **************************************************************
-
-   Adds a property entry to the internal property list.  If there's
-   already an entry with the same key, replace it.
-
-*******************************************************************************/
-
-void properties_add(const char *key, const char *value)
-{
-       list_properties_entry_t *pe;
-
-       /* search for the entry */
-
-       for (pe = list_first(list_properties); pe != NULL;
-                pe = list_next(list_properties, pe)) {
-               if (strcmp(pe->key, key) == 0) {
-                       /* entry was found, replace the value */
-
-#if !defined(NDEBUG)
-                       if (opt_DebugProperties) {
-                               printf("[properties_add: key=%s, old value=%s, new value=%s]\n",
-                                          key, pe->value, value);
-                       }
-#endif
-
-                       pe->value = value;
-
-                       return;
-               }
-       }
-
-       /* entry was not found, insert a new one */
-
-#if !defined(NDEBUG)
-       if (opt_DebugProperties) {
-               printf("[properties_add: key=%s, value=%s]\n", key, value);
-       }
-#endif
-
-       pe = NEW(list_properties_entry_t);
-
-       pe->key   = key;
-       pe->value = value;
-
-       list_add_last(list_properties, pe);
-}
-
-
-/* properties_get **************************************************************
-
-   Get a property entry from the internal property list.
-
-*******************************************************************************/
-
-const char *properties_get(const char *key)
-{
-       list_properties_entry_t *pe;
-
-       for (pe = list_first(list_properties); pe != NULL;
-                pe = list_next(list_properties, pe)) {
-               if (strcmp(pe->key, key) == 0)
-                       return pe->value;
-       }
-
-       return NULL;
-}
-
-
-/* properties_system_add *******************************************************
-
-   Adds a given property to the Java system properties.
-
-*******************************************************************************/
-
-void properties_system_add(java_handle_t *p, const char *key, const char *value)
-{
-       classinfo     *c;
-       methodinfo    *m;
-       java_handle_t *k;
-       java_handle_t *v;
-
-       /* search for method to add properties */
-
-       LLNI_class_get(p, c);
-
-       m = class_resolveclassmethod(c,
-                                                                utf_put,
-                                                                utf_new_char("(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"),
-                                                                NULL,
-                                                                true);
-
-       if (m == NULL)
-               return;
-
-       /* add to the Java system properties */
-
-       k = javastring_new_from_utf_string(key);
-       v = javastring_new_from_utf_string(value);
-
-       (void) vm_call_method(m, p, k, v);
-}
-
-
-/* properties_system_add_all ***************************************************
-
-   Adds all properties from the properties list to the Java system
-   properties.
-
-   ARGUMENTS:
-       p.... is actually a java_util_Properties structure
-
-*******************************************************************************/
-
-#if defined(ENABLE_JAVASE)
-void properties_system_add_all(java_handle_t *p)
-{
-       list_properties_entry_t *pe;
-       classinfo               *c;
-       methodinfo              *m;
-       java_handle_t           *key;
-       java_handle_t           *value;
-
-       /* search for method to add properties */
-
-       LLNI_class_get(p, c);
-
-       m = class_resolveclassmethod(c,
-                                                                utf_put,
-                                                                utf_new_char("(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"),
-                                                                NULL,
-                                                                true);
-
-       if (m == NULL)
-               return;
-
-       /* process all properties stored in the internal table */
-
-       for (pe = list_first(list_properties); pe != NULL;
-                pe = list_next(list_properties, pe)) {
-               /* add to the Java system properties */
-
-               key   = javastring_new_from_utf_string(pe->key);
-               value = javastring_new_from_utf_string(pe->value);
-
-               (void) vm_call_method(m, (java_handle_t *) p, key, value);
-       }
-}
-#endif /* defined(ENABLE_JAVASE) */
-
-
-/* properties_dump *************************************************************
-
-   Dump all property entries.
-
-*******************************************************************************/
-
-void properties_dump(void)
-{
-       list_t                  *l;
-       list_properties_entry_t *pe;
-
-       /* For convenience. */
-
-       l = list_properties;
-
-       for (pe = list_first(l); pe != NULL; pe = list_next(l, pe)) {
-               log_println("[properties_dump: key=%s, value=%s]", pe->key, pe->value);
-       }
-}
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- */
diff --git a/src/vm/properties.cpp b/src/vm/properties.cpp
new file mode 100644 (file)
index 0000000..0be9b5b
--- /dev/null
@@ -0,0 +1,665 @@
+/* src/vm/properties.cpp - handling commandline properties
+
+   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 <errno.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/utsname.h>
+
+#include "mm/memory.h"
+
+#include "native/llni.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.hpp"
+#include "vm/string.hpp"
+#include "vm/vm.hpp"
+
+#include "vm/jit/asmpart.h"
+
+
+/**
+ * Constructor fills the properties list with default values.
+ */
+Properties::Properties()
+{
+       int             len;
+       char           *p;
+
+       char           *boot_class_path;
+
+#if defined(ENABLE_JAVASE)
+
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+       struct utsname *utsnamebuf;
+# endif
+#endif
+
+#if defined(ENABLE_JRE_LAYOUT)
+       /* SUN also uses a buffer of 4096-bytes (strace is your friend). */
+
+       p = MNEW(char, 4096);
+
+       if (os::readlink("/proc/self/exe", p, 4095) == -1)
+               os::abort_errno("readlink failed");
+
+       /* We have a path like:
+
+          /path/to/executable/bin/java
+
+          or
+          
+          /path/to/executeable/jre/bin/java
+
+          Now let's strip two levels. */
+
+       p = os::dirname(p);
+       p = os::dirname(p);
+
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+
+       /* Set java.home. */
+
+       char* java_home = strdup(p);
+
+       /* Set the path to Java core native libraries. */
+
+       len = strlen(java_home) + strlen("/lib/classpath") + strlen("0");
+
+       char* boot_library_path = MNEW(char, len);
+
+       strcpy(boot_library_path, java_home);
+       strcat(boot_library_path, "/lib/classpath");
+
+# elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+
+       /* Find correct java.home.  We check if there is a JRE
+          co-located. */
+
+       /* NOTE: We use the server VM here as it should be available on
+          all architectures. */
+
+       len =
+               strlen(p) +
+               strlen("/jre/lib/"JAVA_ARCH"/server/libjvm.so") +
+               strlen("0");
+
+       char* java_home = MNEW(char, len);
+
+       strcpy(java_home, p);
+       strcat(java_home, "/jre/lib/"JAVA_ARCH"/server/libjvm.so");
+
+       // Check if that libjvm.so exists.
+       if (os::access(java_home, F_OK) == 0) {
+               // Yes, we add /jre to java.home.
+               strcpy(java_home, p);
+               strcat(java_home, "/jre");
+       }
+       else {
+               // No, java.home is parent directory.
+               strcpy(java_home, p);
+       }
+
+       /* Set the path to Java core native libraries. */
+
+       len = strlen(java_home) + strlen("/lib/"JAVA_ARCH) + strlen("0");
+
+       char* boot_library_path = MNEW(char, len);
+
+       strcpy(boot_library_path, java_home);
+       strcat(boot_library_path, "/lib/"JAVA_ARCH);
+
+# else
+#  error unknown classpath configuration
+# endif
+
+       /* Free path. */
+
+       MFREE(p, char, len);
+
+#else
+       const char* java_home = CACAO_PREFIX;
+
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+
+       const char* boot_library_path = JAVA_RUNTIME_LIBRARY_LIBDIR"/classpath";
+
+# elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+
+       const char* boot_library_path = JAVA_RUNTIME_LIBRARY_LIBDIR;
+
+# elif defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
+
+       // No boot_library_path required.
+
+# else
+#  error unknown classpath configuration
+# endif
+#endif
+
+       put("java.home", java_home);
+
+       /* Set the bootclasspath. */
+
+       p = os::getenv("BOOTCLASSPATH");
+
+       if (p != NULL) {
+               boot_class_path = MNEW(char, strlen(p) + strlen("0"));
+               strcpy(boot_class_path, p);
+       }
+       else {
+#if defined(ENABLE_JRE_LAYOUT)
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+
+               len =
+                       strlen(java_home) + strlen("/share/cacao/vm.zip:") +
+                       strlen(java_home) + strlen("/share/classpath/glibj.zip") +
+                       strlen("0");
+
+               boot_class_path = MNEW(char, len);
+
+               strcpy(boot_class_path, java_home);
+               strcat(boot_class_path, "/share/cacao/vm.zip");
+               strcat(boot_class_path, ":");
+               strcat(boot_class_path, java_home);
+               strcat(boot_class_path, "/share/classpath/glibj.zip");
+
+# elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+
+               /* This is the bootclasspath taken from HotSpot (see
+                  hotspot/src/share/vm/runtime/os.cpp
+                  (os::set_boot_path)). */
+
+               len =
+                       strlen(java_home) + strlen("/lib/resources.jar:") +
+                       strlen(java_home) + strlen("/lib/rt.jar:") +
+                       strlen(java_home) + strlen("/lib/sunrsasign.jar:") +
+                       strlen(java_home) + strlen("/lib/jsse.jar:") +
+                       strlen(java_home) + strlen("/lib/jce.jar:") +
+                       strlen(java_home) + strlen("/lib/charsets.jar:") +
+                       strlen(java_home) + strlen("/classes") +
+                       strlen("0");
+
+               boot_class_path = MNEW(char, len);
+
+               strcpy(boot_class_path, java_home);
+               strcat(boot_class_path, "/lib/resources.jar:");
+               strcat(boot_class_path, java_home);
+               strcat(boot_class_path, "/lib/rt.jar:");
+               strcat(boot_class_path, java_home);
+               strcat(boot_class_path, "/lib/sunrsasign.jar:");
+               strcat(boot_class_path, java_home);
+               strcat(boot_class_path, "/lib/jsse.jar:");
+               strcat(boot_class_path, java_home);
+               strcat(boot_class_path, "/lib/jce.jar:");
+               strcat(boot_class_path, java_home);
+               strcat(boot_class_path, "/lib/charsets.jar:");
+               strcat(boot_class_path, java_home);
+               strcat(boot_class_path, "/classes");
+
+# else
+#  error unknown classpath configuration
+# endif
+#else
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+
+               len =
+                       strlen(CACAO_VM_ZIP) +
+                       strlen(":") +
+                       strlen(JAVA_RUNTIME_LIBRARY_CLASSES) +
+                       strlen("0");
+
+               boot_class_path = MNEW(char, len);
+
+               strcpy(boot_class_path, CACAO_VM_ZIP);
+               strcat(boot_class_path, ":");
+               strcat(boot_class_path, JAVA_RUNTIME_LIBRARY_CLASSES);
+
+# elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+
+               /* This is the bootclasspath taken from HotSpot (see
+                  hotspot/src/share/vm/runtime/os.cpp
+                  (os::set_boot_path)). */
+
+               len =
+                       strlen(JAVA_RUNTIME_LIBRARY_PREFIX"/lib/resources.jar:") +
+                       strlen(JAVA_RUNTIME_LIBRARY_PREFIX"/lib/rt.jar:") +
+                       strlen(JAVA_RUNTIME_LIBRARY_PREFIX"/lib/sunrsasign.jar:") +
+                       strlen(JAVA_RUNTIME_LIBRARY_PREFIX"/lib/jsse.jar:") +
+                       strlen(JAVA_RUNTIME_LIBRARY_PREFIX"/lib/jce.jar:") +
+                       strlen(JAVA_RUNTIME_LIBRARY_PREFIX"/lib/charsets.jar:") +
+                       strlen(JAVA_RUNTIME_LIBRARY_PREFIX"/classes") +
+                       strlen("0");
+
+               boot_class_path = MNEW(char, len);
+
+               strcpy(boot_class_path, JAVA_RUNTIME_LIBRARY_PREFIX"/lib/resources.jar:");
+               strcat(boot_class_path, JAVA_RUNTIME_LIBRARY_PREFIX"/lib/rt.jar:");
+               strcat(boot_class_path, JAVA_RUNTIME_LIBRARY_PREFIX"/lib/sunrsasign.jar:");
+               strcat(boot_class_path, JAVA_RUNTIME_LIBRARY_PREFIX"/lib/jsse.jar:");
+               strcat(boot_class_path, JAVA_RUNTIME_LIBRARY_PREFIX"/lib/jce.jar:");
+               strcat(boot_class_path, JAVA_RUNTIME_LIBRARY_PREFIX"/lib/charsets.jar:");
+               strcat(boot_class_path, JAVA_RUNTIME_LIBRARY_PREFIX"/classes");
+
+# elif defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
+
+               len =
+                       strlen(JAVA_RUNTIME_LIBRARY_CLASSES) +
+                       strlen("0");
+
+               boot_class_path = MNEW(char, len);
+
+               strcpy(boot_class_path, JAVA_RUNTIME_LIBRARY_CLASSES);
+
+# else
+#  error unknown classpath configuration
+# endif
+#endif
+       }
+
+       put("sun.boot.class.path", boot_class_path);
+       put("java.boot.class.path", boot_class_path);
+
+#if defined(ENABLE_JAVASE)
+
+       /* Set the classpath. */
+
+       p = os::getenv("CLASSPATH");
+
+       char* class_path;
+
+       if (p != NULL) {
+               class_path = MNEW(char, strlen(p) + strlen("0"));
+               strcpy(class_path, p);
+       }
+       else {
+               class_path = MNEW(char, strlen(".") + strlen("0"));
+               strcpy(class_path, ".");
+       }
+
+       put("java.class.path", class_path);
+
+       // Add java.vm properties.
+       put("java.vm.specification.version", "1.0");
+       put("java.vm.specification.vendor", "Sun Microsystems Inc.");
+       put("java.vm.specification.name", "Java Virtual Machine Specification");
+       put("java.vm.version", VERSION);
+       put("java.vm.vendor", "CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO");
+       put("java.vm.name", "CACAO");
+
+# if defined(ENABLE_INTRP)
+       if (opt_intrp) {
+               /* XXX We don't support java.lang.Compiler */
+/*             put("java.compiler", "cacao.intrp"); */
+               put("java.vm.info", "interpreted mode");
+       }
+       else
+# endif
+       {
+               /* XXX We don't support java.lang.Compiler */
+/*             put("java.compiler", "cacao.jit"); */
+               put("java.vm.info", "compiled mode");
+       }
+
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+
+       /* Get properties from system. */
+
+       char* cwd      = _Jv_getcwd();
+
+       char* env_user = os::getenv("USER");
+       char* env_home = os::getenv("HOME");
+       char* env_lang = os::getenv("LANG");
+
+       utsnamebuf = NEW(struct utsname);
+
+       uname(utsnamebuf);
+
+       put("java.runtime.version", VERSION);
+       put("java.runtime.name", "CACAO");
+
+       put("java.specification.version", "1.5");
+       put("java.specification.vendor", "Sun Microsystems Inc.");
+       put("java.specification.name", "Java Platform API Specification");
+
+       put("java.version", JAVA_VERSION);
+       put("java.vendor", "GNU Classpath");
+       put("java.vendor.url", "http://www.gnu.org/software/classpath/");
+
+       put("java.class.version", CLASS_VERSION);
+
+       put("gnu.classpath.boot.library.path", boot_library_path);
+
+       // Get and set java.library.path.
+       const char* java_library_path = os::getenv("LD_LIBRARY_PATH");
+
+       if (java_library_path == NULL)
+               java_library_path = "";
+
+       put("java.library.path", java_library_path);
+
+       put("java.io.tmpdir", "/tmp");
+
+#  if defined(ENABLE_INTRP)
+       if (opt_intrp) {
+               put("gnu.java.compiler.name", "cacao.intrp");
+       }
+       else
+#  endif
+       {
+               put("gnu.java.compiler.name", "cacao.jit");
+       }
+
+       /* Set the java.ext.dirs property. */
+
+       len = strlen(java_home) + strlen("/jre/lib/ext") + strlen("0");
+
+       char* extdirs = MNEW(char, len);
+
+       sprintf(extdirs, "%s/jre/lib/ext", java_home);
+
+       put("java.ext.dirs", extdirs);
+
+       /* Set the java.ext.endorsed property. */
+
+       len = strlen(java_home) + strlen("/jre/lib/endorsed") + strlen("0");
+
+       char* endorseddirs = MNEW(char, len);
+
+       sprintf(endorseddirs, "%s/jre/lib/endorsed", java_home);
+
+       put("java.endorsed.dirs", endorseddirs);
+
+#  if defined(DISABLE_GC)
+       /* When we disable the GC, we mmap the whole heap to a specific
+          address, so we can compare call traces. For this reason we have
+          to add the same properties on different machines, otherwise
+          more memory may be allocated (e.g. strlen("i386")
+          vs. strlen("alpha"). */
+
+       put("os.arch", "unknown");
+       put("os.name", "unknown");
+       put("os.version", "unknown");
+#  else
+       put("os.arch", JAVA_ARCH);
+       put("os.name", utsnamebuf->sysname);
+       put("os.version", utsnamebuf->release);
+#  endif
+
+#  if WORDS_BIGENDIAN == 1
+       put("gnu.cpu.endian", "big");
+#  else
+       put("gnu.cpu.endian", "little");
+#  endif
+
+       put("file.separator", "/");
+       put("path.separator", ":");
+       put("line.separator", "\n");
+
+       put("user.name", env_user ? env_user : "null");
+       put("user.home", env_home ? env_home : "null");
+       put("user.dir", cwd ? cwd : "null");
+
+       /* get locale */
+
+       if (env_lang != NULL) {
+               /* get the local stuff from the environment */
+
+               if (strlen(env_lang) <= 2) {
+                       put("user.language", env_lang);
+               }
+               else {
+                       if ((env_lang[2] == '_') && (strlen(env_lang) >= 5)) {
+                               char* lang = MNEW(char, 3);
+                               strncpy(lang, (char*) &env_lang[0], 2);
+                               lang[2] = '\0';
+
+                               char* country = MNEW(char, 3);
+                               strncpy(country, (char*) &env_lang[3], 2);
+                               country[2] = '\0';
+
+                               put("user.language", lang);
+                               put("user.country", country);
+                       }
+               }
+       }
+       else {
+               /* if no default locale was specified, use `en_US' */
+
+               put("user.language", "en");
+               put("user.country", "US");
+       }
+
+# elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+
+       /* Actually this property is set by OpenJDK, but we need it in
+          nativevm_preinit(). */
+
+       put("sun.boot.library.path", boot_library_path);
+
+       // Set the java.ext.dirs property.
+       len =
+               strlen(java_home) + strlen("/lib/ext") +
+               strlen(":") +
+               strlen("/usr/java/packages/lib/ext") +
+               strlen("0");
+
+       char* extdirs = MNEW(char, len);
+
+       sprintf(extdirs, "%s/lib/ext:/usr/java/packages/lib/ext", java_home);
+
+       put("java.ext.dirs", extdirs);
+
+       // Set the java.ext.endorsed property.
+       len = strlen(java_home) + strlen("/lib/endorsed") + strlen("0");
+
+       char* endorseddirs = MNEW(char, len);
+
+       sprintf(endorseddirs, "%s/lib/endorsed", java_home);
+
+       put("java.endorsed.dirs", endorseddirs);
+
+# else
+
+#  error unknown classpath configuration
+
+# endif
+
+#elif defined(ENABLE_JAVAME_CLDC1_1)
+
+    put("microedition.configuration", "CLDC-1.1");
+    put("microedition.platform", "generic");
+    put("microedition.encoding", "ISO8859_1");
+    put("microedition.profiles", "");
+
+#else
+
+# error unknown Java configuration
+
+#endif
+}
+
+
+/**
+ * Add the given property to the given Java system properties.
+ *
+ * @param p     Java properties object.
+ * @param key   Key.
+ * @param value Value.
+ */
+void Properties::put(java_handle_t* p, const char* key, const char* value)
+{
+       // Get Properties.put() method to add properties.
+       classinfo* c;
+       LLNI_class_get(p, c);
+
+       methodinfo* m = class_resolveclassmethod(c,
+                                                                                        utf_put,
+                                                                                        utf_new_char("(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"),
+                                                                                        NULL,
+                                                                                        true);
+
+       if (m == NULL)
+               return;
+
+       // Add to the Java system properties.
+       java_handle_t* k = javastring_new_from_utf_string(key);
+       java_handle_t* v = javastring_new_from_utf_string(value);
+
+       (void) vm_call_method(m, p, k, v);
+}
+
+
+/**
+ * Put the given property into the internal property map.  If there's
+ * already an entry with the same key, replace it.
+ *
+ * @param key   Key.
+ * @param value Value.
+ */
+void Properties::put(const char* key, const char* value)
+{
+       // Try to find the key.
+       std::map<const char*, const char*>::iterator it = _properties.find(key);
+
+       // The key is already in the map.
+       if (it != _properties.end()) {
+#if !defined(NDEBUG)
+               if (opt_DebugProperties) {
+                       printf("[Properties::put: key=%s, old value=%s, new value=%s]\n",
+                                  key, it->second, value);
+               }
+#endif
+
+               // Replace the value in the current entry.
+               it->second = value;
+
+               return;
+       }
+
+       // The key was not found, insert the pair.
+#if !defined(NDEBUG)
+       if (opt_DebugProperties) {
+               printf("[Properties::put: key=%s, value=%s]\n", key, value);
+       }
+#endif
+
+       _properties.insert(std::make_pair(key, value));
+}
+
+
+/**
+ * Get a property entry from the internal property map.
+ *
+ * @param key Key.
+ *
+ * @return Value associated with the key or NULL when not found.
+ */
+const char* Properties::get(const char* key)
+{
+       // Try to find the key.
+       std::map<const char*, const char*>::iterator it = _properties.find(key);
+
+       // The key is not in the map.
+       if (it == _properties.end())
+               return NULL;
+
+       // Return the value.
+       return it->second;
+}
+
+
+/**
+ * Fill the given Java system properties with all properties from the
+ * internal properties map.
+ *
+ * @param p Java Properties object.
+ */
+#if defined(ENABLE_JAVASE)
+void Properties::fill(java_handle_t* p)
+{
+       // Get Properties.put() method to add properties.
+       classinfo* c;
+       LLNI_class_get(p, c);
+
+       methodinfo* m = class_resolveclassmethod(c,
+                                                                                        utf_put,
+                                                                                        utf_new_char("(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"),
+                                                                                        NULL,
+                                                                                        true);
+
+       if (m == NULL)
+               return;
+
+       // Iterator over all properties.
+       for (std::map<const char*, const char*>::iterator it = _properties.begin(); it != _properties.end(); it++) {
+               // Put into the Java system properties.
+               java_handle_t* key   = javastring_new_from_utf_string(it->first);
+               java_handle_t* value = javastring_new_from_utf_string(it->second);
+
+               (void) vm_call_method(m, p, key, value);
+       }
+}
+#endif
+
+
+/**
+ * Dump all property entries.
+ */
+#if !defined(NDEBUG)
+void Properties::dump()
+{
+       for (std::map<const char*, const char*>::iterator it = _properties.begin(); it != _properties.end(); it++) {
+               log_println("[Properties::dump: key=%s, value=%s]", it->first, it->second);
+       }
+}
+#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:
+ */
diff --git a/src/vm/properties.h b/src/vm/properties.h
deleted file mode 100644 (file)
index def2ed1..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-/* src/vm/properties.h - handling commandline properties
-
-   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 _PROPERTIES_H
-#define _PROPERTIES_H
-
-#include "config.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <stdint.h>
-
-#include "vm/global.h"
-
-
-/* function prototypes ********************************************************/
-
-void  properties_init(void);
-void  properties_set(void);
-
-void        properties_add(const char *key, const char *value);
-const char *properties_get(const char *key);
-
-void  properties_system_add(java_handle_t *p, const char *key, const char *value);
-
-#if defined(ENABLE_JAVASE)
-void  properties_system_add_all(java_handle_t *p);
-#endif
-
-void  properties_dump(void);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _PROPERTIES_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:
- */
diff --git a/src/vm/properties.hpp b/src/vm/properties.hpp
new file mode 100644 (file)
index 0000000..df2527f
--- /dev/null
@@ -0,0 +1,87 @@
+/* src/vm/properties.hpp - handling commandline properties
+
+   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 _PROPERTIES_HPP
+#define _PROPERTIES_HPP
+
+#include "config.h"
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+
+#include <map>
+
+#include "vm/os.hpp"
+
+
+class ltstr {
+public:
+       bool operator()(const char* s1, const char* s2) const
+       {
+               return os::strcmp(s1, s2) < 0;
+       }
+};
+
+
+/**
+ * Commandline properties.
+ */
+class Properties {
+private:
+       std::map<const char*, const char*, ltstr> _properties;
+
+public:
+       Properties();
+
+       // Static function.
+       static void put(java_handle_t* p, const char* key, const char* value);
+
+       void        put(const char* key, const char* value);
+       const char* get(const char* key);
+       void        fill(java_handle_t* p);
+#if !defined(NDEBUG)
+       void        dump();
+#endif
+};
+
+#endif
+
+#endif // _PROPERTIES_HPP
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
index 73eb721d7dc1b8f2a5bae6abb21bd2585a995a62..ee321cefb4ab64cca5b74a40b704efebc15f6b91 100644 (file)
@@ -63,7 +63,7 @@ typedef union parseddesc {
 
 #include "vm/class.h"
 #include "vm/descriptor.h"
-#include "vm/field.h"
+#include "vm/field.hpp"
 #include "vm/global.h"
 #include "vm/method.h"
 #include "vm/utf8.h"
index 8bd21c916974c5d1f93dd2e0b3a3ce2322696b47..76e588d48e44287414c41e457736aea151750c1c 100644 (file)
 #include "vm/global.h"
 #include "vm/globals.hpp"
 #include "vm/linker.h"
-#include "vm/loader.h"
+#include "vm/loader.hpp"
 #include "vm/options.h"
 #include "vm/primitive.hpp"
 #include "vm/resolve.h"
 
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
 #include "vm/jit/verify/typeinfo.h"
 
 
index fa9ccaddc650c84a450581fb5da787f901ac53d7..cfa0b9205c28344509c5d074c434db000c23de70 100644 (file)
@@ -38,13 +38,15 @@ typedef struct unresolved_subtype_set unresolved_subtype_set;
 #include "vm/types.h"
 
 #include "vm/class.h"
-#include "vm/field.h"
+#include "vm/field.hpp"
 #include "vm/global.h"
 #include "vm/method.h"
 #include "vm/references.h"
 
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
 #include "vm/jit/reg.h"
+
+#include "vm/jit/ir/instruction.hpp"
 #include "vm/jit/verify/typeinfo.h"
 
 
@@ -114,6 +116,10 @@ struct unresolved_method {
 
 /* function prototypes ********************************************************/
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 void resolve_handle_pending_exception(bool throwError);
 
 bool resolve_class_from_name(classinfo* referer,methodinfo *refmethod,
@@ -255,6 +261,10 @@ void unresolved_field_debug_dump(unresolved_field *ref,FILE *file);
 void unresolved_method_debug_dump(unresolved_method *ref,FILE *file);
 void unresolved_subtype_set_debug_dump(unresolved_subtype_set *stset,FILE *file);
 #endif
+
+#ifdef __cplusplus
+}
+#endif
        
 #endif /* _RESOLVE_H */
 
index b8b84104b506534b98d761ccdef0e893baf0875d..345db3dd2b2bc281c5efb9ef73c4dfe1f2407b82 100644 (file)
@@ -44,6 +44,7 @@
 #endif
 
 #include "threads/thread.hpp"
+#include "threads/threadlist.hpp"
 
 #include "vm/exceptions.hpp"
 #include "vm/globals.hpp"
@@ -138,7 +139,7 @@ bool signal_init(void)
                                                           SA_NODEFER | SA_SIGINFO);
 #  endif
 
-#  if defined(__ARM__) || defined(__I386__) || defined(__S390__) || defined(__X86_64__) || defined(__M68K__)
+#  if defined(__ALPHA__) || defined(__ARM__) || defined(__I386__) || defined(__MIPS__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__S390__) || defined(__X86_64__) || defined(__M68K__)
                /* XXX use better defines for that (in arch.h) */
                /* SIGILL handler */
 
@@ -316,7 +317,7 @@ void signal_thread_handler(int sig)
        case SIGQUIT:
                /* print a thread dump */
 #if defined(ENABLE_THREADS)
-               threads_dump();
+               ThreadList_dump_threads();
 #endif
 
 #if defined(ENABLE_STATISTICS)
index 799e4bfcb1da6243c18c24d4c891e3e8325c2426..469d949a47a05ec7a0904247dbc18bccf271e26e 100644 (file)
@@ -64,7 +64,7 @@ void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p);
 void md_signal_handler_sigfpe(int sig, siginfo_t *siginfo, void *_p);
 #endif
 
-#if defined(__ARM__) || defined(__I386__) || defined(__S390__) || defined(__X86_64__) || defined(__M68K__)
+#if defined(__ALPHA__) || defined(__ARM__) || defined(__I386__) || defined(__MIPS__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__S390__) || defined(__X86_64__) || defined(__M68K__)
 /* XXX use better defines for that (in arch.h) */
 void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p);
 #endif
index 690349c7a4b34f243ef9f69c52592c63b0c87610..14ac1f801bb89721df39705ae5619982a990694f 100644 (file)
@@ -34,7 +34,7 @@
 #include "vm/options.h"
 #include "vm/stackmap.h"
 #include "vm/statistics.h"
-#include "vm/suck.h"
+#include "vm/suck.hpp"
 
 
 /* stackmap_get_verification_type_info *****************************************
index e2c6b9378d01d48e3ede75d0f22ee1a28978eed2..ff9c5e581072e6cc6d1fbe81ca72af1c60aea689 100644 (file)
@@ -53,7 +53,7 @@ typedef struct Uninitialized_variable_info_t     Uninitialized_variable_info_t;
 #include "vm/types.h"
 
 #include "vm/global.h"
-#include "vm/loader.h"
+#include "vm/loader.hpp"
 #include "vm/method.h"
 
 
index 37d19460707d5b98c0cc460a00d44d014a394c92..46aa681f7e8bec6aee5d0e9853273aaa239cc87f 100644 (file)
 
 #include "toolbox/logging.h"
 
+#include "threads/thread.hpp"
+
 #include "vm/class.h"
-#include "vm/field.h"
+#include "vm/field.hpp"
 #include "vm/global.h"
 #include "vm/method.h"
 #include "vm/options.h"
 #include "vm/statistics.h"
 
-#include "vm/jit/code.h"
+#include "vm/jit/code.hpp"
 
 
 /* global variables ***********************************************************/
@@ -304,12 +306,25 @@ s8 getcputime(void)
 
 *******************************************************************************/
 
+Mutex *loadingtime_lock = Mutex_new();
+
 void loadingtime_start(void)
 {
+       Mutex_lock(loadingtime_lock);
+
        loadingtime_recursion++;
 
        if (loadingtime_recursion == 1)
                loadingstarttime = getcputime();
+       else {
+               int end = getcputime();
+               loadingtime += (end - loadingstarttime);
+
+               loadingstarttime = loadingstoptime = end;
+       }
+       
+
+       Mutex_unlock(loadingtime_lock);
 }
 
 
@@ -321,12 +336,18 @@ void loadingtime_start(void)
 
 void loadingtime_stop(void)
 {
-       if (loadingtime_recursion == 1) {
-               loadingstoptime = getcputime();
-               loadingtime += (loadingstoptime - loadingstarttime);
+       Mutex_lock(loadingtime_lock);
+
+       loadingstoptime = getcputime();
+       loadingtime += (loadingstoptime - loadingstarttime);
+
+       if (loadingtime_recursion > 1) {
+               loadingstarttime = loadingstoptime;
        }
 
        loadingtime_recursion--;
+
+       Mutex_unlock(loadingtime_lock);
 }
 
 
index 46bebed985232e50a1586295cc1d4743ab5b9870..d84cf4da89777c765130d8f4b311530dce8c3de4 100644 (file)
@@ -231,6 +231,10 @@ extern s4 count_schedule_critical_path;
 
 /* function prototypes ********************************************************/
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 s8 getcputime(void);
 
 void loadingtime_start(void);
@@ -251,6 +255,10 @@ void compiledinvokation(void);
 void jnicallXmethodnvokation(void);
 void jniinvokation(void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* _STATISTICS_H */
 
 
index 71224d06b9389768353e857f39108c54f78db1e0..184f8f66cf742b936a148e9e9b386598f2a4259a 100644 (file)
 
 #include "mm/memory.h"
 
-#include "native/jni.h"
 #include "native/llni.h"
 
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
 
-#include "vm/array.h"
-#include "vm/builtin.h"
+#include "vm/array.hpp"
+#include "vm/jit/builtin.hpp"
 #include "vm/exceptions.hpp"
 #include "vm/globals.hpp"
 #include "vm/javaobjects.hpp"
@@ -50,7 +49,6 @@
 #include "vm/statistics.h"
 #include "vm/string.hpp"
 #include "vm/utf8.h"
-#include "vm/vm.hpp"
 
 
 /* global variables ***********************************************************/
@@ -108,8 +106,7 @@ void stringtable_update(void)
                                
                                if (js.is_null() || (js.get_value() == NULL)) {
                                        /* error in hashtable found */
-
-                                       vm_abort("stringtable_update: invalid literalstring in hashtable");
+                                       os::abort("stringtable_update: invalid literalstring in hashtable");
                                }
 
                                a = LLNI_UNWRAP(js.get_value());
@@ -525,7 +522,7 @@ static java_object_t *literalstring_u2(java_chararray_t *a, int32_t length,
 #endif
 
 #if defined(ENABLE_THREADS)
-       lock_init_object_lock(o);
+       o->lockword.init();
 #endif
 
        o->vftbl = class_java_lang_String->vftbl;
diff --git a/src/vm/suck.c b/src/vm/suck.c
deleted file mode 100644 (file)
index ddbf0f8..0000000
+++ /dev/null
@@ -1,627 +0,0 @@
-/* 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:
- */
diff --git a/src/vm/suck.cpp b/src/vm/suck.cpp
new file mode 100644 (file)
index 0000000..522abe1
--- /dev/null
@@ -0,0 +1,619 @@
+/* src/vm/suck.cpp - 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/mutex.hpp"
+
+#include "toolbox/list.hpp"
+#include "toolbox/logging.h"
+#include "toolbox/util.h"
+
+#include "vm/exceptions.hpp"
+#include "vm/loader.hpp"
+#include "vm/options.h"
+#include "vm/os.hpp"
+#include "vm/properties.hpp"
+#include "vm/suck.hpp"
+#include "vm/vm.hpp"
+#include "vm/zip.h"
+
+
+/* global variables ***********************************************************/
+
+List<list_classpath_entry*>* list_classpath_entries;
+
+
+/* suck_init *******************************************************************
+
+   Initializes the suck subsystem like initializing the classpath
+   entries list.
+
+*******************************************************************************/
+
+bool suck_init(void)
+{
+       TRACESUBSYSTEMINITIALIZATION("suck_init");
+
+#warning Move this list into VM.
+       list_classpath_entries = new List<list_classpath_entry*>();
+
+       /* everything's ok */
+
+       return true;
+}
+
+
+/* scandir_filter **************************************************************
+
+   Filters for zip/jar files.
+
+*******************************************************************************/
+
+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
+                               os::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_classpath_entries->push_back(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;
+       s4              pathlen;
+       struct dirent **namelist;
+       s4              n;
+       s4              i;
+       s4              namlen;
+       char           *p;
+
+       /* get the property value */
+       Properties properties = VM::get_current()->get_properties();
+       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;
+                       char* 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((const char*) path, &namelist, &scandir_filter, (int (*)(const void*, const void*)) &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*.
+                                       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.put("sun.boot.class.path", p);
+                                       properties.put("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)
+{
+       u8 a;
+
+       a = SUCK_BE_U8(cb->pos);
+       cb->pos += 8;
+
+       return a;
+}
+
+
+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 (List<list_classpath_entry*>::iterator it = list_classpath_entries->begin(); it != list_classpath_entries->end() && cb == NULL; it++) {
+               lce = *it;
+
+#if defined(ENABLE_ZLIB)
+               if (lce->type == CLASSPATH_ARCHIVE) {
+
+                       /* enter a monitor on zip/jar archives */
+
+                       lce->mutex->lock();
+
+                       /* try to get the file in current archive */
+
+                       cb = zip_get(lce, c);
+
+                       /* leave the monitor */
+
+                       lce->mutex->unlock();
+
+               } 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:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
diff --git a/src/vm/suck.h b/src/vm/suck.h
deleted file mode 100644 (file)
index da06570..0000000
+++ /dev/null
@@ -1,207 +0,0 @@
-/* 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:
- */
diff --git a/src/vm/suck.hpp b/src/vm/suck.hpp
new file mode 100644 (file)
index 0000000..0db6a57
--- /dev/null
@@ -0,0 +1,206 @@
+/* src/vm/suck.hpp - 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_HPP
+#define _SUCK_HPP
+
+#include "config.h"
+
+#include "vm/types.h"
+
+#include "threads/mutex.hpp"
+
+#include "toolbox/hashtable.h"
+#include "toolbox/list.hpp"
+
+#include "vm/class.h"
+#include "vm/global.h"
+#include "vm/loader.hpp"
+
+
+/* list_classpath_entry *******************************************************/
+
+enum {
+       CLASSPATH_PATH,
+       CLASSPATH_ARCHIVE
+};
+
+typedef struct list_classpath_entry list_classpath_entry;
+
+struct list_classpath_entry {
+#if defined(ENABLE_THREADS)
+       Mutex             *mutex;               /* mutex locking on zip/jar files */
+#endif
+       s4                 type;
+       char              *path;
+       s4                 pathlen;
+#if defined(ENABLE_ZLIB)
+       hashtable         *htclasses;
+#endif
+};
+
+
+/* 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))
+#define SUCK_LE_U8(p)    *((u8 *) (p))
+
+#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]))
+
+#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 /* 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]))
+
+#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]))
+
+
+#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 ***********************************************************/
+
+#ifdef __cplusplus
+extern List<list_classpath_entry*>* list_classpath_entries;
+#else
+extern List* list_classpath_entries;
+#endif
+
+/* function prototypes ********************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool suck_init(void);
+
+void suck_add(char *classpath);
+void suck_add_from_property(const char *key);
+
+bool suck_check_classbuffer_size(classbuffer *cb, s4 len);
+
+u1 suck_u1(classbuffer *cb);
+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_HPP
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
index 7616aa117f1823a25a1e3bd1495f3fb6bca97f90..1d7d7605fae6a4565acb47c69aabb3e3eb8c4479 100644 (file)
@@ -32,7 +32,7 @@
 
 #include "mm/memory.h"
 
-#include "threads/lock-common.h"
+#include "threads/mutex.hpp"
 
 #include "toolbox/hashtable.h"
 
@@ -691,7 +691,7 @@ utf *utf_new(const char *text, u2 length)
        utf *u;                             /* hashtable element                  */
        u2 i;
 
-       LOCK_MONITOR_ENTER(hashtable_utf->header);
+       Mutex_lock(hashtable_utf->mutex);
 
 #if defined(ENABLE_STATISTICS)
        if (opt_stat)
@@ -719,7 +719,7 @@ utf *utf_new(const char *text, u2 length)
 
                        /* symbol found in hashtable */
 
-                       LOCK_MONITOR_EXIT(hashtable_utf->header);
+                       Mutex_unlock(hashtable_utf->mutex);
 
                        return u;
                }
@@ -792,7 +792,7 @@ utf *utf_new(const char *text, u2 length)
                hashtable_utf = newhash;
        }
 
-       LOCK_MONITOR_EXIT(hashtable_utf->header);
+       Mutex_unlock(hashtable_utf->mutex);
 
        return u;
 }
@@ -812,7 +812,7 @@ utf *utf_new_u2(u2 *unicode_pos, u4 unicode_length, bool isclassname)
        u4 left;                        /* unicode characters left                */
        u4 buflength;                   /* utf length in bytes of the u2 array    */
        utf *result;                    /* resulting utf-string                   */
-       int i;          
+       int i;
 
        /* determine utf length in bytes and allocate memory */
 
index 91d2a2d9c66577ea82d2b4de13ee8daba383fab6..8a1197ebf619715b50361bf5c851cea3a950dc17 100644 (file)
@@ -226,6 +226,10 @@ extern utf *array_packagename;
 
 /* function prototypes ********************************************************/
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /* initialize the utf8 subsystem */
 void utf8_init(void);
 
@@ -289,6 +293,10 @@ bool is_valid_name_utf(utf *u);
 /* show utf-table */
 void utf_show(void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* _UTF_H */
 
 
diff --git a/src/vm/vftbl.hpp b/src/vm/vftbl.hpp
new file mode 100644 (file)
index 0000000..80f45a8
--- /dev/null
@@ -0,0 +1,125 @@
+/* src/vm/vftbl.hpp - virtual function table
+
+   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 _VFTBL_HPP
+#define _VFTBL_HPP
+
+// Forward declaration.
+typedef struct _vftbl vftbl_t;
+
+#include "config.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 ---> +---------------+
+
+*******************************************************************************/
+
+// Includes.
+#include "vm/class.h"
+#include "vm/references.h"
+
+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                         */
+};
+
+#endif // _VFTBL_HPP
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
index dc956a961f2bb16749a86fbf9edc4fc07d2493f9..b713e82098ae05e3767d707449c1fcf3209a3c82 100644 (file)
 #include "vm/jit/abi-asm.h"
 
 #include "mm/codememory.h"
+#include "mm/dumpmemory.hpp"
 #include "mm/gc.hpp"
 #include "mm/memory.h"
 
-#include "native/jni.h"
+#include "native/jni.hpp"
 #include "native/llni.h"
-#include "native/localref.h"
-#include "native/native.h"
+#include "native/localref.hpp"
+#include "native/native.hpp"
 
-#include "native/vm/nativevm.h"
+#include "native/vm/nativevm.hpp"
 
-#include "threads/lock-common.h"
-#include "threads/threadlist.h"
+#include "threads/lock.hpp"
 #include "threads/thread.hpp"
 
 #include "toolbox/logging.h"
 
-#include "vm/array.h"
+#include "vm/array.hpp"
 
 #if defined(ENABLE_ASSERTION)
-#include "vm/assertion.h"
+#include "vm/assertion.hpp"
 #endif
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/classcache.h"
 #include "vm/exceptions.hpp"
 #include "vm/finalizer.h"
 #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/properties.hpp"
 #include "vm/signallocal.h"
 #include "vm/statistics.h"
 #include "vm/string.hpp"
-#include "vm/suck.h"
+#include "vm/suck.hpp"
 #include "vm/vm.hpp"
 
-#include "vm/jit/argument.h"
+#include "vm/jit/argument.hpp"
 #include "vm/jit/asmpart.h"
-#include "vm/jit/code.h"
+#include "vm/jit/code.hpp"
 
 #if defined(ENABLE_DISASSEMBLER)
 # include "vm/jit/disass.h"
 #endif
 
-#include "vm/jit/jit.h"
 #include "vm/jit/jitcache.hpp"
 #include "vm/jit/methodtree.h"
 
@@ -97,7 +95,7 @@
 # include "vm/jit/optimizing/profile.h"
 #endif
 
-#include "vm/jit/optimizing/recompile.h"
+#include "vm/jit/optimizing/recompiler.hpp"
 
 #if defined(ENABLE_PYTHON)
 # include "vm/jit/python.h"
 
 
 /**
- * This is _the_ instance of the VM.
+ * This is _the_ VM instance.
  */
-VM* vm;
+VM* VM::_vm = NULL;
 
 
 /* global variables ***********************************************************/
@@ -194,7 +192,6 @@ enum {
        /* CACAO options */
 
        OPT_VERBOSE1,
-       OPT_NOIEEE,
 
 #if defined(ENABLE_STATISTICS)
        OPT_TIME,
@@ -315,9 +312,6 @@ opt_struct opts[] = {
 #if defined(ENABLE_VERIFIER) && defined(TYPECHECK_VERBOSE)
        { "verbosetc",         false, OPT_VERBOSETC },
 #endif
-#if defined(__ALPHA__)
-       { "noieee",            false, OPT_NOIEEE },
-#endif
 #if defined(ENABLE_STATISTICS)
        { "time",              false, OPT_TIME },
        { "stat",              false, OPT_STAT },
@@ -510,9 +504,6 @@ static void XXusage(void)
 #ifdef TYPECHECK_VERBOSE
        puts("    -verbosetc               write debug messages while typechecking");
 #endif
-#if defined(__ALPHA__)
-       puts("    -noieee                  don't use ieee compliant arithmetic");
-#endif
 #if defined(ENABLE_VERIFIER)
        puts("    -noverify                don't verify classfiles");
 #endif
@@ -607,53 +598,6 @@ static void fullversion(void)
 }
 
 
-static void vm_printconfig(void)
-{
-       puts("Configure/Build options:\n");
-       puts("  ./configure: "VERSION_CONFIGURE_ARGS"");
-#if defined(__VERSION__)
-       puts("  CC         : "VERSION_CC" ("__VERSION__")");
-#else
-       puts("  CC         : "VERSION_CC"");
-#endif
-       puts("  CFLAGS     : "VERSION_CFLAGS"\n");
-
-       puts("Default variables:\n");
-       printf("  maximum heap size              : %d\n", HEAP_MAXSIZE);
-       printf("  initial heap size              : %d\n", HEAP_STARTSIZE);
-       printf("  stack size                     : %d\n", STACK_SIZE);
-
-#if defined(ENABLE_JRE_LAYOUT)
-       /* When we're building with JRE-layout, the default paths are the
-          same as the runtime paths. */
-#else
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-       puts("  gnu.classpath.boot.library.path: "JAVA_RUNTIME_LIBRARY_LIBDIR);
-       puts("  java.boot.class.path           : "CACAO_VM_ZIP":"JAVA_RUNTIME_LIBRARY_CLASSES"");
-# elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-       puts("  sun.boot.library.path          : "JAVA_RUNTIME_LIBRARY_LIBDIR);
-       puts("  java.boot.class.path           : "JAVA_RUNTIME_LIBRARY_CLASSES);
-# endif
-#endif
-
-       puts("");
-
-       puts("Runtime variables:\n");
-       printf("  maximum heap size              : %d\n", opt_heapmaxsize);
-       printf("  initial heap size              : %d\n", opt_heapstartsize);
-       printf("  stack size                     : %d\n", opt_stacksize);
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-       printf("  gnu.classpath.boot.library.path: %s\n", properties_get("gnu.classpath.boot.library.path"));
-#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-       printf("  sun.boot.library.path          : %s\n", properties_get("sun.boot.library.path"));
-#endif
-
-       printf("  java.boot.class.path           : %s\n", properties_get("java.boot.class.path"));
-       printf("  java.class.path                : %s\n", properties_get("java.class.path"));
-}
-
-
 /* forward declarations *******************************************************/
 
 static char *vm_get_mainclass_from_jar(char *mainstring);
@@ -682,7 +626,7 @@ bool VM::create(JavaVM** p_vm, void** p_env, void* vm_args)
 
        // Instantiate a new VM.
        try {
-               vm = new VM(_vm_args);
+               _vm = new VM(_vm_args);
        }
        catch (std::exception e) {
                // FIXME How can we delete the resources allocated?
@@ -690,15 +634,15 @@ bool VM::create(JavaVM** p_vm, void** p_env, void* vm_args)
 //             FREE(env, _Jv_JNIEnv);
 //             FREE(vm, _Jv_JavaVM);
 
-               vm = NULL;
+               _vm = NULL;
 
                return false;
        }
 
        // Return the values.
 
-       *p_vm  = vm->get_javavm();
-       *p_env = vm->get_jnienv();
+       *p_vm  = _vm->get_javavm();
+       *p_env = _vm->get_jnienv();
 
        return true;
 }
@@ -725,7 +669,7 @@ VM::VM(JavaVMInitArgs* vm_args)
 
        // Make ourself globally visible.
        // XXX Is this a good idea?
-       vm = this;
+       _vm = this;
 
        /* create and fill a JavaVM structure */
 
@@ -776,25 +720,18 @@ VM::VM(JavaVMInitArgs* vm_args)
        /* Install the exit handler. */
 
        if (atexit(vm_exit_handler))
-               vm_abort("atexit failed: %s\n", strerror(errno));
+               os::abort("atexit failed: %s\n", strerror(errno));
 
        /* Set some options. */
 
        opt_version       = false;
        opt_exit          = false;
 
-       opt_noieee        = false;
-
        opt_heapmaxsize   = HEAP_MAXSIZE;
        opt_heapstartsize = HEAP_STARTSIZE;
        opt_stacksize     = STACK_SIZE;
 
-       /* Initialize the properties list before command-line handling.
-          Otherwise -XX:+PrintConfig crashes. */
-
-       properties_init();
-
-       /* First of all, parse the -XX options. */
+       // First of all, parse the -XX options.
 
 #if defined(ENABLE_VMLOG)
        vmlog_cacao_init_options();
@@ -802,6 +739,11 @@ VM::VM(JavaVMInitArgs* vm_args)
 
        options_xx(vm_args);
 
+       // After -XX options are parsed, print the build-time
+       // configuration, if requested.
+       if (opt_PrintConfig)
+               print_build_time_config();
+
 #if defined(ENABLE_VMLOG)
        vmlog_cacao_init();
 #endif
@@ -823,10 +765,6 @@ VM::VM(JavaVMInitArgs* vm_args)
        jvmti = false;
 #endif
 
-       /* Fill the properties before command-line handling. */
-
-       properties_set();
-
        /* iterate over all passed options */
 
        while ((opt = options_get(opts, vm_args)) != OPT_DONE) {
@@ -861,14 +799,14 @@ VM::VM(JavaVMInitArgs* vm_args)
                           classpath. */
 
                        // FIXME Make class_path const char*.
-                       class_path = (char*) properties_get("java.class.path");
+                       class_path = (char*) _properties.get("java.class.path");
 
                        p = MNEW(char, strlen(opt_arg) + strlen("0"));
 
                        strcpy(p, opt_arg);
 
 #if defined(ENABLE_JAVASE)
-                       properties_add("java.class.path", p);
+                       _properties.put("java.class.path", p);
 #endif
 
                        MFREE(class_path, char, strlen(class_path));
@@ -878,14 +816,14 @@ VM::VM(JavaVMInitArgs* vm_args)
                        for (unsigned int i = 0; i < strlen(opt_arg); i++) {
                                if (opt_arg[i] == '=') {
                                        opt_arg[i] = '\0';
-                                       properties_add(opt_arg, opt_arg + i + 1);
+                                       _properties.put(opt_arg, opt_arg + i + 1);
                                        goto opt_d_done;
                                }
                        }
 
                        /* if no '=' is given, just create an empty property */
 
-                       properties_add(opt_arg, "");
+                       _properties.put(opt_arg, "");
 
                opt_d_done:
                        break;
@@ -895,14 +833,14 @@ VM::VM(JavaVMInitArgs* vm_args)
                           new boot classpath. */
 
                        // FIXME Make boot_class_path const char*.
-                       boot_class_path = (char*) properties_get("sun.boot.class.path");
+                       boot_class_path = (char*) _properties.get("sun.boot.class.path");
 
                        p = MNEW(char, strlen(opt_arg) + strlen("0"));
 
                        strcpy(p, opt_arg);
 
-                       properties_add("sun.boot.class.path", p);
-                       properties_add("java.boot.class.path", p);
+                       _properties.put("sun.boot.class.path", p);
+                       _properties.put("java.boot.class.path", p);
 
                        MFREE(boot_class_path, char, strlen(boot_class_path));
                        break;
@@ -911,7 +849,7 @@ VM::VM(JavaVMInitArgs* vm_args)
                        /* Append to bootclasspath. */
 
                        // FIXME Make boot_class_path const char*.
-                       boot_class_path = (char*) properties_get("sun.boot.class.path");
+                       boot_class_path = (char*) _properties.get("sun.boot.class.path");
 
                        len = strlen(boot_class_path);
 
@@ -925,15 +863,15 @@ VM::VM(JavaVMInitArgs* vm_args)
                        strcat(p, ":");
                        strcat(p, opt_arg);
 
-                       properties_add("sun.boot.class.path", p);
-                       properties_add("java.boot.class.path", p);
+                       _properties.put("sun.boot.class.path", p);
+                       _properties.put("java.boot.class.path", p);
                        break;
 
                case OPT_BOOTCLASSPATH_P:
                        /* Prepend to bootclasspath. */
 
                        // FIXME Make boot_class_path const char*.
-                       boot_class_path = (char*) properties_get("sun.boot.class.path");
+                       boot_class_path = (char*) _properties.get("sun.boot.class.path");
 
                        len = strlen(boot_class_path);
 
@@ -943,8 +881,8 @@ VM::VM(JavaVMInitArgs* vm_args)
                        strcat(p, ":");
                        strcat(p, boot_class_path);
 
-                       properties_add("sun.boot.class.path", p);
-                       properties_add("java.boot.class.path", p);
+                       _properties.put("sun.boot.class.path", p);
+                       _properties.put("java.boot.class.path", p);
 
                        MFREE(boot_class_path, char, len);
                        break;
@@ -954,7 +892,7 @@ VM::VM(JavaVMInitArgs* vm_args)
                           classes. */
 
                        // FIXME Make boot_class_path const char*.
-                       boot_class_path = (char*) properties_get("sun.boot.class.path");
+                       boot_class_path = (char*) _properties.get("sun.boot.class.path");
 
                        len =
                                strlen(CACAO_VM_ZIP) +
@@ -968,8 +906,8 @@ VM::VM(JavaVMInitArgs* vm_args)
                        strcat(p, ":");
                        strcat(p, opt_arg);
 
-                       properties_add("sun.boot.class.path", p);
-                       properties_add("java.boot.class.path", p);
+                       _properties.put("sun.boot.class.path", p);
+                       _properties.put("java.boot.class.path", p);
 
                        MFREE(boot_class_path, char, strlen(boot_class_path));
                        break;
@@ -1089,10 +1027,6 @@ VM::VM(JavaVMInitArgs* vm_args)
                        opt_version = true;
                        break;
 
-               case OPT_NOIEEE:
-                       opt_noieee = true;
-                       break;
-
 #if defined(ENABLE_VERIFIER)
                case OPT_NOVERIFY:
                        opt_verify = false;
@@ -1177,10 +1111,6 @@ VM::VM(JavaVMInitArgs* vm_args)
                                        opt_showdisassemble = true;
                                        compileverbose = true;
                                        break;
-
-                               case 'o':
-                                       opt_shownops = true;
-                                       break;
 #endif
 
                                case 'd':
@@ -1371,6 +1301,11 @@ VM::VM(JavaVMInitArgs* vm_args)
                }
        }
 
+       // Print the preliminary run-time VM configuration after options
+       // are parsed.
+       if (opt_PrintConfig)
+               print_run_time_config();
+
 #if defined(ENABLE_JVMTI)
        if (jvmti) {
                jvmti_set_phase(JVMTI_PHASE_ONLOAD);
@@ -1388,10 +1323,6 @@ VM::VM(JavaVMInitArgs* vm_args)
        gc_init(opt_heapmaxsize, opt_heapstartsize);
 
 #if defined(ENABLE_THREADS)
-       /* BEFORE: threads_preinit */
-
-       threadlist_init();
-
        /* AFTER: gc_init */
 
        threads_preinit();
@@ -1401,7 +1332,7 @@ VM::VM(JavaVMInitArgs* vm_args)
        /* install architecture dependent signal handlers */
 
        if (!signal_init())
-               vm_abort("vm_create: signal_init failed");
+               os::abort("vm_create: signal_init failed");
 
 #if defined(ENABLE_INTRP)
        /* Allocate main thread stack on the Java heap. */
@@ -1415,7 +1346,7 @@ VM::VM(JavaVMInitArgs* vm_args)
        /* AFTER: threads_preinit */
 
        if (!string_init())
-               vm_abort("vm_create: string_init failed");
+               os::abort("vm_create: string_init failed");
 
        /* AFTER: threads_preinit */
 
@@ -1424,7 +1355,7 @@ VM::VM(JavaVMInitArgs* vm_args)
        /* AFTER: thread_preinit */
 
        if (!suck_init())
-               vm_abort("vm_create: suck_init failed");
+               os::abort("vm_create: suck_init failed");
 
        suck_add_from_property("java.endorsed.dirs");
 
@@ -1439,14 +1370,14 @@ VM::VM(JavaVMInitArgs* vm_args)
        /* AFTER: utf8_init */
 
        // FIXME Make boot_class_path const char*.
-       boot_class_path = (char*) properties_get("sun.boot.class.path");
+       boot_class_path = (char*) _properties.get("sun.boot.class.path");
        suck_add(boot_class_path);
 
        /* initialize the classcache hashtable stuff: lock, hashtable
           (must be done _after_ threads_preinit) */
 
        if (!classcache_init())
-               vm_abort("vm_create: classcache_init failed");
+               os::abort("vm_create: classcache_init failed");
 
        /* Initialize the code memory management. */
        /* AFTER: threads_preinit */
@@ -1457,7 +1388,7 @@ VM::VM(JavaVMInitArgs* vm_args)
           threads_preinit) */
 
        if (!finalizer_init())
-               vm_abort("vm_create: finalizer_init failed");
+               os::abort("vm_create: finalizer_init failed");
 
        /* Initialize the JIT compiler. */
 
@@ -1469,25 +1400,19 @@ VM::VM(JavaVMInitArgs* vm_args)
        pythonpass_init();
 #endif
 
-       /* BEFORE: loader_preinit */
-
-       Package::initialize();
-
        /* AFTER: utf8_init, classcache_init */
 
        loader_preinit();
        linker_preinit();
 
-       /* AFTER: loader_preinit, linker_preinit */
-
-       primitive_init();
+       // AFTER: loader_preinit, linker_preinit
+       Primitive::initialize_table();
 
        loader_init();
        linker_init();
 
-       /* AFTER: loader_init, linker_init */
-
-       primitive_postinit();
+       // AFTER: loader_init, linker_init
+       Primitive::post_initialize_table();
        method_init();
 
 #if defined(ENABLE_JIT)
@@ -1495,13 +1420,7 @@ VM::VM(JavaVMInitArgs* vm_args)
 #endif
 
        if (!builtin_init())
-               vm_abort("vm_create: builtin_init failed");
-
-       /* Initialize the native subsystem. */
-       /* BEFORE: threads_init */
-
-       if (!native_init())
-               vm_abort("vm_create: native_init failed");
+               os::abort("vm_create: builtin_init failed");
 
        /* Register the native methods implemented in the VM. */
        /* BEFORE: threads_init */
@@ -1514,7 +1433,7 @@ VM::VM(JavaVMInitArgs* vm_args)
           (e.g. NewGlobalRef). */
 
        if (!jni_init())
-               vm_abort("vm_create: jni_init failed");
+               os::abort("vm_create: jni_init failed");
 #endif
 
 #if defined(ENABLE_JNI) || defined(ENABLE_HANDLES)
@@ -1522,7 +1441,7 @@ VM::VM(JavaVMInitArgs* vm_args)
        /* BEFORE: threads_init */
 
        if (!localref_table_init())
-               vm_abort("vm_create: localref_table_init failed");
+               os::abort("vm_create: localref_table_init failed");
 #endif
 
        /* Iinitialize some important system classes. */
@@ -1543,15 +1462,10 @@ VM::VM(JavaVMInitArgs* vm_args)
        /* initialize profiling */
 
        if (!profile_init())
-               vm_abort("vm_create: profile_init failed");
+               os::abort("vm_create: profile_init failed");
 #endif
 
 #if defined(ENABLE_THREADS)
-       /* initialize recompilation */
-
-       if (!recompile_init())
-               vm_abort("vm_create: recompile_init failed");
-
        /* start the signal handler thread */
 
 #if defined(__LINUX__)
@@ -1559,33 +1473,32 @@ VM::VM(JavaVMInitArgs* vm_args)
        if (threads_pthreads_implementation_nptl)
 #endif
                if (!signal_start_thread())
-                       vm_abort("vm_create: signal_start_thread failed");
+                       os::abort("vm_create: signal_start_thread failed");
 
        /* finally, start the finalizer thread */
 
        if (!finalizer_start_thread())
-               vm_abort("vm_create: finalizer_start_thread failed");
+               os::abort("vm_create: finalizer_start_thread failed");
 
 # if !defined(NDEBUG)
        /* start the memory profiling thread */
 
        if (opt_ProfileMemoryUsage || opt_ProfileGCMemoryUsage)
                if (!memory_start_thread())
-                       vm_abort("vm_create: memory_start_thread failed");
+                       os::abort("vm_create: memory_start_thread failed");
 # endif
 
-       /* start the recompilation thread (must be done before the
-          profiling thread) */
-
-       if (!recompile_start_thread())
-               vm_abort("vm_create: recompile_start_thread failed");
+       // Start the recompilation thread (must be done before the
+       // profiling thread).
+       // FIXME Only works for one recompiler.
+       _recompiler.start();
 
 # if defined(ENABLE_PROFILING)
        /* start the profile sampling thread */
 
 /*     if (opt_prof) */
 /*             if (!profile_start_thread()) */
-/*                     vm_abort("vm_create: profile_start_thread failed"); */
+/*                     os::abort("vm_create: profile_start_thread failed"); */
 # endif
 #endif
 
@@ -1608,11 +1521,75 @@ VM::VM(JavaVMInitArgs* vm_args)
        _created      = true;
        _initializing = false;
        
-       /* Print the VM configuration after all stuff is set and the VM is
-          initialized. */
-
+       // Print the run-time VM configuration after all stuff is set and
+       // the VM is initialized.
        if (opt_PrintConfig)
-               vm_printconfig();
+               print_run_time_config();
+}
+
+
+/**
+ * Print build-time (default) VM configuration.
+ */
+void VM::print_build_time_config(void)
+{
+       puts("CACAO "VERSION" configure/build options:");
+       puts("");
+       puts("  ./configure: "VERSION_CONFIGURE_ARGS"");
+#if defined(__VERSION__)
+       puts("  CC         : "VERSION_CC" ("__VERSION__")");
+       puts("  CXX        : "VERSION_CXX" ("__VERSION__")");
+#else
+       puts("  CC         : "VERSION_CC"");
+       puts("  CXX        : "VERSION_CXX"");
+#endif
+       puts("  CFLAGS     : "VERSION_CFLAGS"");
+       puts("  CXXFLAGS   : "VERSION_CXXFLAGS"");
+
+       puts("");
+
+       puts("Build-time (default) variables:\n");
+       printf("  maximum heap size              : %d\n", HEAP_MAXSIZE);
+       printf("  initial heap size              : %d\n", HEAP_STARTSIZE);
+       printf("  stack size                     : %d\n", STACK_SIZE);
+
+#if defined(ENABLE_JRE_LAYOUT)
+       // When we're building with JRE-layout, the default paths are the
+       // same as the runtime paths.
+#else
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+       puts("  gnu.classpath.boot.library.path: "JAVA_RUNTIME_LIBRARY_LIBDIR);
+       puts("  java.boot.class.path           : "CACAO_VM_ZIP":"JAVA_RUNTIME_LIBRARY_CLASSES"");
+# elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+       puts("  sun.boot.library.path          : "JAVA_RUNTIME_LIBRARY_LIBDIR);
+       puts("  java.boot.class.path           : "JAVA_RUNTIME_LIBRARY_CLASSES);
+# endif
+#endif
+
+       puts("");
+}
+
+
+/**
+ * Print run-time VM configuration.
+ */
+void VM::print_run_time_config()
+{
+       puts("Run-time variables:\n");
+       printf("  maximum heap size              : %d\n", opt_heapmaxsize);
+       printf("  initial heap size              : %d\n", opt_heapstartsize);
+       printf("  stack size                     : %d\n", opt_stacksize);
+
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+       printf("  gnu.classpath.boot.library.path: %s\n", _properties.get("gnu.classpath.boot.library.path"));
+#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+       printf("  sun.boot.library.path          : %s\n", _properties.get("sun.boot.library.path"));
+#endif
+
+       printf("  java.boot.class.path           : %s\n", _properties.get("java.boot.class.path"));
+       printf("  java.class.path                : %s\n", _properties.get("java.class.path"));
+
+       puts("");
 }
 
 
@@ -1665,7 +1642,7 @@ void vm_run(JavaVM *vm, JavaVMInitArgs *vm_args)
                        strcpy(p, mainname);
 
 #if defined(ENABLE_JAVASE)
-                       properties_add("java.class.path", p);
+                       VM::get_current()->get_properties().put("java.class.path", p);
 #endif
                }
                else {
@@ -1805,7 +1782,7 @@ void vm_run(JavaVM *vm, JavaVMInitArgs *vm_args)
           the application's main method exits. */
 
        if (!thread_detach_current_thread())
-               vm_abort("vm_run: Could not detach main thread.");
+               os::abort("vm_run: Could not detach main thread.");
 #endif
 
        /* Destroy the JavaVM. */
@@ -2007,89 +1984,6 @@ void vm_exit_handler(void)
 }
 
 
-/* vm_abort ********************************************************************
-
-   Prints an error message and aborts the VM.
-
-   IN:
-       text ... error message to print
-
-*******************************************************************************/
-
-void vm_abort(const char *text, ...)
-{
-       va_list ap;
-
-       /* Print the log message. */
-
-       log_start();
-
-       va_start(ap, text);
-       log_vprint(text, ap);
-       va_end(ap);
-
-       log_finish();
-
-       /* Now abort the VM. */
-
-       os::abort();
-}
-
-
-/* vm_abort_errnum *************************************************************
-
-   Prints an error message, appends ":" plus the strerror-message of
-   errnum and aborts the VM.
-
-   IN:
-       errnum ... error number
-       text ..... error message to print
-
-*******************************************************************************/
-
-void vm_abort_errnum(int errnum, const char *text, ...)
-{
-       va_list ap;
-
-       /* Print the log message. */
-
-       log_start();
-
-       va_start(ap, text);
-       log_vprint(text, ap);
-       va_end(ap);
-
-       /* Print the strerror-message of errnum. */
-
-       log_print(": %s", os::strerror(errnum));
-
-       log_finish();
-
-       /* Now abort the VM. */
-
-       os::abort();
-}
-
-
-/* vm_abort_errno **************************************************************
-
-   Equal to vm_abort_errnum, but uses errno to get the error number.
-
-   IN:
-       text ... error message to print
-
-*******************************************************************************/
-
-void vm_abort_errno(const char *text, ...)
-{
-       va_list ap;
-
-       va_start(ap, text);
-       vm_abort_errnum(errno, text, ap);
-       va_end(ap);
-}
-
-
 /* vm_abort_disassemble ********************************************************
 
    Prints an error message, disassemble the given code range (if
@@ -2136,7 +2030,7 @@ void vm_abort_disassemble(void *pc, int count, const char *text, ...)
                pc = disassinstr((u1*) pc);
 #endif
 
-       vm_abort("Aborting...");
+       os::abort("Aborting...");
 }
 
 
@@ -2377,7 +2271,7 @@ static void vm_compile_method(char* mainname)
        }
 
        if (m == NULL)
-               vm_abort("vm_compile_method: java.lang.NoSuchMethodException: %s.%s",
+               os::abort("vm_compile_method: java.lang.NoSuchMethodException: %s.%s",
                                 opt_method, opt_signature ? opt_signature : "");
                
        jit_compile(m);
@@ -2479,19 +2373,18 @@ type vm_call_method##name##_valist(methodinfo *m, java_handle_t *o,     \
 {                                                                       \
        uint64_t *array;                                                    \
        type      value;                                                    \
-       int32_t   dumpmarker;                                               \
                                                                         \
        if (m->code == NULL)                                                \
                if (!jit_compile(m))                                            \
                        return 0;                                                   \
                                                                         \
        THREAD_NATIVEWORLD_EXIT;                                            \
-       DMARKER;                                                            \
+                                                                                                                                               \
+       DumpMemoryArea dma;                                                                                                     \
                                                                         \
        array = argument_vmarray_from_valist(m, o, ap);                     \
        value = vm_call##name##_array(m, array);                            \
                                                                         \
-       DRELEASE;                                                           \
        THREAD_NATIVEWORLD_ENTER;                                           \
                                                                         \
        return value;                                                       \
@@ -2517,19 +2410,18 @@ type vm_call_method##name##_jvalue(methodinfo *m, java_handle_t *o,     \
 {                                                                       \
        uint64_t *array;                                                    \
        type      value;                                                    \
-       int32_t   dumpmarker;                                               \
                                                                         \
        if (m->code == NULL)                                                \
                if (!jit_compile(m))                                            \
                        return 0;                                                   \
                                                                         \
        THREAD_NATIVEWORLD_EXIT;                                            \
-       DMARKER;                                                            \
+                                                                                                                                               \
+       DumpMemoryArea dma;                                                                                                     \
                                                                         \
        array = argument_vmarray_from_jvalue(m, o, args);                   \
        value = vm_call##name##_array(m, array);                            \
                                                                         \
-       DRELEASE;                                                           \
        THREAD_NATIVEWORLD_ENTER;                                           \
                                                                         \
        return value;                                                       \
@@ -2556,7 +2448,6 @@ java_handle_t *vm_call_method_objectarray(methodinfo *m, java_handle_t *o,
        java_handle_t *xptr;
        java_handle_t *ro;
        imm_union      value;
-       int32_t        dumpmarker;
 
        /* Prevent compiler warnings. */
 
@@ -2572,19 +2463,14 @@ java_handle_t *vm_call_method_objectarray(methodinfo *m, java_handle_t *o,
 
        THREAD_NATIVEWORLD_EXIT;
 
-       /* mark start of dump memory area */
-
-       DMARKER;
+       // Create new dump memory area.
+       DumpMemoryArea dma;
 
        /* Fill the argument array from a object-array. */
 
        array = argument_vmarray_from_objectarray(m, o, params);
 
        if (array == NULL) {
-               /* release dump area */
-
-               DRELEASE;
-
                /* enter the nativeworld again */
 
                THREAD_NATIVEWORLD_ENTER;
@@ -2624,13 +2510,9 @@ java_handle_t *vm_call_method_objectarray(methodinfo *m, java_handle_t *o,
                break;
 
        default:
-               vm_abort("vm_call_method_objectarray: invalid return type %d", m->parseddesc->returntype.primitivetype);
+               os::abort("vm_call_method_objectarray: invalid return type %d", m->parseddesc->returntype.primitivetype);
        }
 
-       /* release dump area */
-
-       DRELEASE;
-
        /* enter the nativeworld again */
 
        THREAD_NATIVEWORLD_ENTER;
@@ -2660,11 +2542,38 @@ java_handle_t *vm_call_method_objectarray(methodinfo *m, java_handle_t *o,
 
 extern "C" {
 
-JavaVM* VM_get_javavm()      { return vm->get_javavm(); }
-JNIEnv* VM_get_jnienv()      { return vm->get_jnienv(); }
-bool    VM_is_initializing() { return vm->is_initializing(); }
-bool    VM_is_created()      { return vm->is_created(); }
-int64_t VM_get_starttime()   { return vm->get_starttime(); }
+JavaVM* VM_get_javavm()      { return VM::get_current()->get_javavm(); }
+JNIEnv* VM_get_jnienv()      { return VM::get_current()->get_jnienv(); }
+bool    VM_is_initializing() { return VM::get_current()->is_initializing(); }
+bool    VM_is_created()      { return VM::get_current()->is_created(); }
+int64_t VM_get_starttime()   { return VM::get_current()->get_starttime(); }
+
+void vm_abort(const char* text, ...)
+{
+       va_list ap;
+
+       va_start(ap, text);
+       os::abort(text, ap);
+       va_end(ap);
+}
+
+void vm_abort_errnum(int errnum, const char* text, ...)
+{
+       va_list ap;
+
+       va_start(ap, text);
+       os::abort_errnum(errnum, text, ap);
+       va_end(ap);
+}
+
+void vm_abort_errno(const char* text, ...)
+{
+       va_list ap;
+
+       va_start(ap, text);
+       os::abort_errno(text, ap);
+       va_end(ap);
+}
 
 }
 
index e074b7a48fa0e7982adde16b4dd16b356b2543a0..6e3d54d37c09e765d89ec7ba476d451dce388b3a 100644 (file)
 #include <stdarg.h>
 #include <stdint.h>
 
-#include "vm/types.h"
+// We need the JNI types for the VM class.
+#include "native/jni.hpp"
+#include "native/native.hpp"
 
-#include "native/jni.h"
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+# include "native/vm/openjdk/hpi.hpp"
+# include "native/vm/openjdk/management.hpp"
+#endif
 
-#include "vm/global.h"
+#include "vm/properties.hpp"
+
+#include "vm/jit/optimizing/recompiler.hpp"
 
-#include "vm/class.h"
-#include "vm/method.h"
 
 #ifdef __cplusplus
 
@@ -47,6 +52,9 @@
  */
 class VM {
 private:
+       // This is _the_ VM instance.
+       static VM* _vm;
+
        // JNI variables.
        JavaVM* _javavm;
        JNIEnv* _jnienv;
@@ -57,6 +65,18 @@ private:
        bool    _exiting;
        int64_t _starttime;
 
+       // Subsystems.
+       Properties      _properties;      ///< Commandline properties.
+#if defined(ENABLE_THREADS)
+       Recompiler      _recompiler;      ///< JIT recompilation framework.
+#endif
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+       HPI             _hpi;             ///< Host Porting Interface.
+       Management      _management;      ///< Java management interface.
+#endif
+       NativeLibraries _nativelibraries; ///< Native library table.
+       NativeMethods   _nativemethods;   ///< Native methods table.
+
 public:
        // Constructor, Destructor.
        VM(JavaVMInitArgs*);
@@ -64,6 +84,10 @@ public:
 
        // Static methods.
        static bool create(JavaVM** p_vm, void** p_env, void* vm_args);
+       static VM*  get_current() { return _vm; }
+
+       static void print_build_time_config();
+       void        print_run_time_config();
 
        // Getters for private members.
        JavaVM* get_javavm()      { return _javavm; }
@@ -72,13 +96,16 @@ public:
        bool    is_created()      { return _created; }
        bool    is_exiting()      { return _exiting; }
        int64_t get_starttime()   { return _starttime; }
-};
-
 
-/**
- * This is _the_ instance of the VM.
- */
-extern VM* vm;
+       Properties&      get_properties     () { return _properties; }
+       Recompiler&      get_recompiler     () { return _recompiler; } // REMOVEME
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+       HPI&             get_hpi            () { return _hpi; }
+       Management&      get_management     () { return _management; }
+#endif
+       NativeLibraries& get_nativelibraries() { return _nativelibraries; }
+       NativeMethods&   get_nativemethods  () { return _nativemethods; }
+};
 
 #else
 
@@ -90,6 +117,12 @@ int64_t VM_get_starttime();
 
 #endif
 
+
+// Includes.
+#include "vm/global.h"
+#include "vm/method.h"
+
+
 /* These C methods are the exported interface. ********************************/
 
 #ifdef __cplusplus
@@ -106,7 +139,7 @@ bool VM_create(JavaVM** p_vm, void** p_env, void* vm_args);
 /* export global variables ****************************************************/
 
 #if defined(ENABLE_INTRP)
-extern u1 *intrp_main_stack;
+extern uint8_t* intrp_main_stack;
 #endif
 
 
@@ -120,15 +153,12 @@ void usage(void);
 
 bool vm_create(JavaVMInitArgs *vm_args);
 void vm_run(JavaVM *vm, JavaVMInitArgs *vm_args);
-s4   vm_destroy(JavaVM *vm);
-void vm_exit(s4 status);
-void vm_shutdown(s4 status);
+int32_t   vm_destroy(JavaVM *vm);
+void vm_exit(int32_t status);
+void vm_shutdown(int32_t status);
 
 void vm_exit_handler(void);
 
-void vm_abort(const char *text, ...);
-void vm_abort_errnum(int errnum, const char *text, ...);
-void vm_abort_errno(const char *text, ...);
 void vm_abort_disassemble(void *pc, int count, const char *text, ...);
 
 /* Java method calling functions */
@@ -157,6 +187,12 @@ double  vm_call_method_double_jvalue(methodinfo *m, java_handle_t *o, const jval
 
 java_handle_t *vm_call_method_objectarray(methodinfo *m, java_handle_t *o, java_handle_objectarray_t *params);
 
+
+// Legacy C interface.
+void vm_abort(const char* text, ...);
+void vm_abort_errnum(int errnum, const char* text, ...);
+void vm_abort_errno(const char* text, ...);
+
 #ifdef __cplusplus
 }
 #endif
index da8f0782984af9bbecebc7ab94b476b99fcb5387..109156079fab28f0eb31d453ba7124ea34b55564 100644 (file)
 
 #include "vm/types.h"
 
+#include "vm/descriptor.h" /* needed to prevent circular dependency */
 #include "toolbox/hashtable.h"
 
 #include "mm/memory.h"
 
 #include "vm/global.h"
-#include "vm/suck.h"
+#include "vm/suck.hpp"
 #include "vm/utf8.h"
 #include "vm/vm.hpp"
 #include "vm/zip.h"
index 0e22cc57ed456e516b725a417dcf1bc20b973d53..f36382f06b2a204c96e6e40564f0c5d42aaf3e27 100644 (file)
 #ifndef _ZIP_H
 #define _ZIP_H
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #include "config.h"
 #include "vm/types.h"
 
@@ -37,8 +33,8 @@ extern "C" {
 
 #include "vm/class.h"
 #include "vm/global.h"
-#include "vm/loader.h"
-#include "vm/suck.h"
+#include "vm/loader.hpp"
+#include "vm/suck.hpp"
 #include "vm/utf8.h"
 
 
@@ -93,6 +89,10 @@ struct hashtable_zipfile_entry {
 
 /* function prototypes ********************************************************/
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 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);
index 62a57afe71e6fcfde6771adacdf1e1027ddf3070..5d7eca6246a7aadfd587534a72129e49462d53c0 100644 (file)
@@ -1,9 +1,7 @@
 /* src/tests/native/checkjni.c - for testing JNI stuff
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
-   C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
-   E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
-   TU Wien
+   Copyright (C) 1996-2005, 2006, 2008
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
 
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Christian Thalinger
-
-   Changes:
-
 */
 
 
+#include "config.h"
+
 #include <stdio.h>
 #include <string.h>
 
-#include "config.h"
-#include "native/jni.h"
+#include INCLUDE_JNI_MD_H
+#include INCLUDE_JNI_H
 
 
 JNIEXPORT jboolean JNICALL Java_checkjni_IsAssignableFrom(JNIEnv *env, jclass clazz, jclass sub, jclass sup)
index 3d568f66dafa9fb825abdc49f18843d76225996d..f6a0777496511cfb5bfd400897ef948763c57c6c 100644 (file)
@@ -1,9 +1,7 @@
 /* tests/native/test.c - for testing native stuff
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
-   C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
-   E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
-   TU Wien
+   Copyright (C) 1996-2005, 2006, 2008
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
 
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Christian Thalinger
-
-
 */
 
 
+#include "config.h"
+
 #include <stdio.h>
 
-#include "config.h"
-#include "native/jni.h"
+#include "native/jni.hpp"
 
 
 JNIEXPORT void JNICALL Java_test_nsub(JNIEnv *env, jclass clazz)
index bc7be27c52c0de4bf940e988039fa4b3545a9640..d2b3f36c37b57825c9e00ff5b176ba7e4e47feb8 100644 (file)
@@ -1,9 +1,7 @@
 /* tests/regression/native/testarguments.c - tests argument passing
 
-   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,
-   TU Wien
+   Copyright (C) 1996-2005, 2006, 2007, 2008
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
 
 
 #include "config.h"
 
+#include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 
-#include "native/jni.h"
+#include INCLUDE_JNI_MD_H
+#include INCLUDE_JNI_H
 
 
 JNIEXPORT jobject JNICALL Java_testarguments_adr(JNIEnv *env, jclass clazz, jint i)
index 2bce8e1f10a09e0c9bf956ff03d689497b958e3e..961025bf4b46dda946f8ef95a9d3f03c6e8ae68c 100644 (file)
@@ -1,9 +1,7 @@
 /* tests/native/testgetobjectclass0.c - tests argument passing
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
-   C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
-   E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
-   TU Wien
+   Copyright (C) 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: Joseph Wenninger
-
-
 */
 
 
 #include "config.h"
-#include "native/jni.h"
+#include "native/jni.hpp"
 
 
 JNIEXPORT void JNICALL Java_testgetobjectclass0_getobjectclass0(JNIEnv *env, jclass clazz)
diff --git a/tests/threads/sableContention.java b/tests/threads/sableContention.java
new file mode 100644 (file)
index 0000000..184dc31
--- /dev/null
@@ -0,0 +1,91 @@
+// This pathological test tries to grow a FLC list as long as possible before
+// the threads from the previous FLC list have resumed running. Every one on
+// the old list then has to scan the entire new list.
+
+// The CACAO patch in file sableContention.patch can be used to examine the
+// maximum length. With 500 threads on a quad-core system, I managed to get to
+// about 120.
+
+class sableContention {
+       public Object a[] = null;
+       public tt ts[] = null;
+       final int NUM = 500;
+
+       class tt extends Thread {
+               sableContention y;
+               int x;
+               tt(sableContention y, int x) {
+                       this.y = y;
+                       this.x = x;
+               }
+               public void run() {
+                       int i = 1;
+                       synchronized(y.a[x]) {
+                               if (x==0) {
+                                       for (; i<NUM*3/4; i++)
+                                               y.ts[i].start();
+                                       y.a[x].notify();
+                               }
+                       }
+                       if (x==0)
+                               for (; i<NUM; i++)
+                                       y.ts[i].start();
+                       for (int j=0; j<NUM/10; j++)
+                               synchronized(y.a[(x+j)%(NUM-1)+1]) {
+                               }
+               }
+       }
+
+       private void l(int f) {
+               try {
+                       synchronized(a[NUM-1-f]) {
+                               if (f > 0) {
+                                       l(f-1);
+                                       if (f<10)
+                                               Thread.sleep(0, f*100 * 1000);
+                               }
+                               else {
+                                       ts = new tt[NUM];
+                                       for (int i=0; i<NUM; i++)
+                                               ts[i] = new tt(this, i);
+                                       ts[0].start();
+                                       a[0].wait();
+                               }
+                       }
+               } catch (InterruptedException e) {
+               }
+       }
+
+       private void r() {
+               for (;;) {
+                       a = new Object[NUM];
+                       for (int i=0; i<NUM; i++)
+                               a[i] = new Object();
+                       l(NUM-1);
+                       for (int i=0; i<NUM; i++)
+                               try {
+                                       ts[i].join();
+                               } catch (InterruptedException e) {
+                               }
+                       System.out.println("running");
+               }
+       }
+
+       public static void main(String[] args) {
+               new sableContention().r();
+       }
+}
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: java
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
diff --git a/tests/threads/sableContention.patch b/tests/threads/sableContention.patch
new file mode 100644 (file)
index 0000000..f83a4a6
--- /dev/null
@@ -0,0 +1,29 @@
+--- a/src/threads/lock.cpp     Thu Sep 11 14:52:50 2008 +0200
++++ b/src/threads/lock.cpp     Thu Sep 11 15:13:24 2008 +0200
+@@ -717,6 +717,7 @@
+               for (;;)
+               {
+                       threadobject *current;
++                      int i = 0;
+                       // Wait until another thread sees the flc bit and notifies
+                       // us of unlocking.
+@@ -726,8 +727,17 @@
+                               break;
+                       /* Traverse FLC list looking if we're still there */
+                       current = t_other->flc_list;
+-                      while (current && current != t)
++                      while (current && current != t) {
++                              i++;
+                               current = current->flc_next;
++                      }
++                      {
++                              static int umax = 0;
++                              if (i>umax) {
++                                      printf("sable len %d\n", i);
++                                      umax = i;
++                              }
++                      }
+                       if (!current)
+                               /* not in list anymore, can stop waiting */
+                               break;