* src/toolbox/avl.h (avl_tree): Renamed to avl_tree_t.
[cacao.git] / src / vm / jit / codegen-common.c
index cc933b6c80f07bca5870d5fa0c6608f424d9d275..669ffec53363181b42e422934005d126bd111eee 100644 (file)
@@ -1,9 +1,9 @@
 /* src/vm/jit/codegen-common.c - architecture independent code generator stuff
 
 /* src/vm/jit/codegen-common.c - architecture independent code generator stuff
 
-   Copyright (C) 1996-2005 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 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 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
 
    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: Reinhard Grafl
-            Andreas  Krall
-
-   Changes: Christian Thalinger
-            Joseph Wenninger
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
 
    All functions assume the following code area / data area layout:
 
 
    All functions assume the following code area / data area layout:
 
@@ -47,7 +39,7 @@
    memory. All functions writing values into the data area return the offset
    relative the begin of the code area (start of procedure).   
 
    memory. All functions writing values into the data area return the offset
    relative the begin of the code area (start of procedure).   
 
-   $Id: codegen-common.c 4203 2006-01-13 19:37:17Z twisti $
+   $Id: codegen-common.c 7859 2007-05-03 08:29:16Z twisti $
 
 */
 
 
 */
 
@@ -60,7 +52,7 @@
 #include "vm/types.h"
 
 #if defined(ENABLE_JIT)
 #include "vm/types.h"
 
 #if defined(ENABLE_JIT)
-/* this is required for gen_resolvebranch and PATCHER_CALL_SIZE */
+/* this is required PATCHER_CALL_SIZE */
 # include "codegen.h"
 #endif
 
 # include "codegen.h"
 #endif
 
 #endif
 
 #include "mm/memory.h"
 #endif
 
 #include "mm/memory.h"
+
 #include "toolbox/avl.h"
 #include "toolbox/avl.h"
+#include "toolbox/list.h"
 #include "toolbox/logging.h"
 #include "toolbox/logging.h"
+
 #include "native/jni.h"
 #include "native/native.h"
 
 #include "native/jni.h"
 #include "native/native.h"
 
-#if defined(USE_THREADS)
-# if defined(NATIVE_THREADS)
-#  include "threads/native/threads.h"
-# else
-#  include "threads/green/threads.h"
-# endif
-#endif
+#include "threads/threads-common.h"
 
 #include "vm/exceptions.h"
 
 #include "vm/exceptions.h"
-#include "vm/method.h"
-#include "vm/options.h"
-#include "vm/statistics.h"
 #include "vm/stringlocal.h"
 #include "vm/stringlocal.h"
+
+#include "vm/jit/abi.h"
 #include "vm/jit/asmpart.h"
 #include "vm/jit/codegen-common.h"
 #include "vm/jit/asmpart.h"
 #include "vm/jit/codegen-common.h"
-#include "vm/jit/disass.h"
+
+#if defined(ENABLE_DISASSEMBLER)
+# include "vm/jit/disass.h"
+#endif
+
 #include "vm/jit/dseg.h"
 #include "vm/jit/dseg.h"
+#include "vm/jit/emit-common.h"
 #include "vm/jit/jit.h"
 #include "vm/jit/jit.h"
+#include "vm/jit/md.h"
+#include "vm/jit/replace.h"
 #include "vm/jit/stacktrace.h"
 
 #include "vm/jit/stacktrace.h"
 
+#if defined(ENABLE_INTRP)
+#include "vm/jit/intrp/intrp.h"
+#endif
+
+#include "vmcore/method.h"
+#include "vmcore/options.h"
+
+# include "vmcore/statistics.h"
+
+#if defined(ENABLE_VMLOG)
+#include <vmlog_cacao.h>
+#endif
+
 
 /* in this tree we store all method addresses *********************************/
 
 
 /* in this tree we store all method addresses *********************************/
 
-#if defined(__I386__) || defined(__X86_64__) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
-static avl_tree *methodtree = NULL;
+static avl_tree_t *methodtree = NULL;
 static s4 methodtree_comparator(const void *pc, const void *element);
 static s4 methodtree_comparator(const void *pc, const void *element);
-#endif
 
 
 /* codegen_init ****************************************************************
 
 
 /* codegen_init ****************************************************************
@@ -112,7 +118,6 @@ static s4 methodtree_comparator(const void *pc, const void *element);
 
 void codegen_init(void)
 {
 
 void codegen_init(void)
 {
-#if defined(__I386__) || defined(__X86_64__) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
        /* this tree is global, not method specific */
 
        if (!methodtree) {
        /* this tree is global, not method specific */
 
        if (!methodtree) {
@@ -123,44 +128,47 @@ void codegen_init(void)
                methodtree = avl_create(&methodtree_comparator);
 
 #if defined(ENABLE_JIT)
                methodtree = avl_create(&methodtree_comparator);
 
 #if defined(ENABLE_JIT)
-               /* insert asm_calljavafunction */
-
-               mte = NEW(methodtree_element);
-
-               mte->startpc = (u1 *) (ptrint) asm_calljavafunction;
-               mte->endpc   = (u1 *) ((ptrint) asm_calljavafunction2 - 1);
-
-               avl_insert(methodtree, mte);
-
-               /* insert asm_calljavafunction2 */
+               /* insert asm_vm_call_method */
 
                mte = NEW(methodtree_element);
 
 
                mte = NEW(methodtree_element);
 
-               mte->startpc = (u1 *) (ptrint) asm_calljavafunction2;
-               mte->endpc   = (u1 *) ((ptrint) asm_call_jit_compiler - 1);
+               mte->startpc = (u1 *) (ptrint) asm_vm_call_method;
+               mte->endpc   = (u1 *) (ptrint) asm_vm_call_method_end;
 
                avl_insert(methodtree, mte);
 #endif /* defined(ENABLE_JIT) */
        }
 
                avl_insert(methodtree, mte);
 #endif /* defined(ENABLE_JIT) */
        }
-#endif /* defined(__I386__) || defined(__X86_64__) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
 }
 
 
 }
 
 
-/* codegen_setup **************************************************************
+/* codegen_setup ***************************************************************
 
 
-   allocates and initialises code area, data area and references
+   Allocates and initialises code area, data area and references.
 
 *******************************************************************************/
 
 
 *******************************************************************************/
 
-void codegen_setup(methodinfo *m, codegendata *cd, t_inlining_globals *id)
+void codegen_setup(jitdata *jd)
 {
 {
-       cd->mcodebase = DMNEW(u1, MCODEINITSIZE);
-       cd->mcodesize = MCODEINITSIZE;
+       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 */
 
        /* initialize mcode variables */
-       
-       cd->mcodeptr = cd->mcodebase;
-       cd->mcodeend = (s4 *) (cd->mcodebase + MCODEINITSIZE);
+
+       cd->mcodeptr     = cd->mcodebase;
+       cd->lastmcodeptr = cd->mcodebase;
 
 #if defined(ENABLE_INTRP)
        /* native dynamic superinstructions variables */
 
 #if defined(ENABLE_INTRP)
        /* native dynamic superinstructions variables */
@@ -177,83 +185,159 @@ void codegen_setup(methodinfo *m, codegendata *cd, t_inlining_globals *id)
                cd->superstarts = NULL;
        }
 #endif
                cd->superstarts = NULL;
        }
 #endif
-       
-       cd->dsegtop = DMNEW(u1, DSEGINITSIZE);
-       cd->dsegsize = DSEGINITSIZE;
-       cd->dsegtop += cd->dsegsize;
-       cd->dseglen = 0;
+
+       cd->dseg           = NULL;
+       cd->dseglen        = 0;
 
        cd->jumpreferences = NULL;
 
 
        cd->jumpreferences = NULL;
 
-#if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(ENABLE_INTRP)
+#if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
        cd->datareferences = NULL;
 #endif
 
        cd->datareferences = NULL;
 #endif
 
-       cd->xboundrefs = NULL;
-       cd->xnullrefs = NULL;
-       cd->xcastrefs = NULL;
-       cd->xstorerefs = NULL;
-       cd->xdivrefs = NULL;
-       cd->xexceptionrefs = NULL;
-       cd->patchrefs = NULL;
+/*     cd->patchrefs      = list_create_dump(OFFSET(patchref, linkage)); */
+       cd->patchrefs      = NULL;
+       cd->brancheslabel  = list_create_dump(OFFSET(branch_label_ref_t, linkage));
 
        cd->linenumberreferences = NULL;
        cd->linenumbertablesizepos = 0;
        cd->linenumbertablestartpos = 0;
        cd->linenumbertab = 0;
        
 
        cd->linenumberreferences = NULL;
        cd->linenumbertablesizepos = 0;
        cd->linenumbertablestartpos = 0;
        cd->linenumbertab = 0;
        
-       cd->method = m;
-       cd->exceptiontable = 0;
-       cd->exceptiontablelength = 0;
-
-       if (useinlining && id) {
-               if (id->cumextablelength > 0) {
-                       cd->exceptiontablelength = id->cumextablelength;
-                       cd->exceptiontable =
-                               DMNEW(exceptiontable, id->cumextablelength + 1);
-               }
+#if defined(ENABLE_THREADS)
+       cd->threadcritcurrent.next = NULL;
+       cd->threadcritcount = 0;
+#endif
+}
 
 
-       } else if (id && (id->method->exceptiontablelength > 0)) {
-               cd->exceptiontablelength = m->exceptiontablelength;
-               cd->exceptiontable = DMNEW(exceptiontable, m->exceptiontablelength + 1);
-       }
 
 
-       if (id) {
-               cd->maxstack = id->cummaxstack;
-               cd->maxlocals = id->cumlocals;
-       } else {
-               cd->maxstack = m->maxstack;
-               cd->maxlocals = m->maxlocals;
-       }
+/* codegen_reset ***************************************************************
 
 
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+   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->patchrefs       = list_create_dump(OFFSET(patchref, linkage)); */
+       cd->patchrefs       = NULL;
+       cd->brancheslabel   = list_create_dump(OFFSET(branch_label_ref_t, linkage));
+
+       cd->linenumberreferences    = NULL;
+       cd->linenumbertablesizepos  = 0;
+       cd->linenumbertablestartpos = 0;
+       cd->linenumbertab           = 0;
+       
+#if defined(ENABLE_THREADS)
        cd->threadcritcurrent.next = NULL;
        cd->threadcritcurrent.next = NULL;
-       cd->threadcritcount = 0;
+       cd->threadcritcount        = 0;
+#endif
+
+       /* 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;
+       }
+
+#if defined(ENABLE_REPLACEMENT)
+       code->rplpoints     = NULL;
+       code->rplpointcount = 0;
+       code->regalloc      = NULL;
+       code->regalloccount = 0;
+       code->globalcount   = 0;
 #endif
 }
 
 
 #endif
 }
 
 
-/* codegen_free ****************************************************************
+/* codegen_generate ************************************************************
 
 
-   Releases temporary code and data area.
+   Generates the code for the currently compiled method.
 
 *******************************************************************************/
 
 
 *******************************************************************************/
 
-void codegen_free(methodinfo *m, codegendata *cd)
+bool codegen_generate(jitdata *jd)
 {
 {
-#if 0
-       if (cd) {
-               if (cd->mcodebase) {
-                       MFREE(cd->mcodebase, u1, cd->mcodesize);
-                       cd->mcodebase = NULL;
-               }
+       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 (cd->dsegtop) {
-                       MFREE(cd->dsegtop - cd->dsegsize, u1, cd->dsegsize);
-                       cd->dsegtop = NULL;
+       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
 #endif
+       }
+
+       /* reallocate the memory and finish the code generation */
+
+       codegen_finish(jd);
+
+       /* everything's ok */
+
+       return true;
 }
 
 
 }
 
 
@@ -275,7 +359,7 @@ void codegen_close(void)
 
 *******************************************************************************/
 
 
 *******************************************************************************/
 
-s4 *codegen_increase(codegendata *cd, u1 *mcodeptr)
+void codegen_increase(codegendata *cd)
 {
        u1 *oldmcodebase;
 
 {
        u1 *oldmcodebase;
 
@@ -290,7 +374,11 @@ s4 *codegen_increase(codegendata *cd, u1 *mcodeptr)
                                                          cd->mcodesize,
                                                          cd->mcodesize * 2);
        cd->mcodesize *= 2;
                                                          cd->mcodesize,
                                                          cd->mcodesize * 2);
        cd->mcodesize *= 2;
-       cd->mcodeend   = (s4 *) (cd->mcodebase + cd->mcodesize);
+       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(ENABLE_INTRP)
        /* adjust the pointer to the last patcher position */
 
 #if defined(__I386__) || defined(__MIPS__) || defined(__X86_64__) || defined(ENABLE_INTRP)
        /* adjust the pointer to the last patcher position */
@@ -298,10 +386,6 @@ s4 *codegen_increase(codegendata *cd, u1 *mcodeptr)
        if (cd->lastmcodeptr != NULL)
                cd->lastmcodeptr = cd->mcodebase + (cd->lastmcodeptr - oldmcodebase);
 #endif
        if (cd->lastmcodeptr != NULL)
                cd->lastmcodeptr = cd->mcodebase + (cd->lastmcodeptr - oldmcodebase);
 #endif
-
-       /* return the new mcodeptr */
-
-       return (s4 *) (cd->mcodebase + (mcodeptr - oldmcodebase));
 }
 
 
 }
 
 
@@ -335,194 +419,137 @@ u1 *codegen_ncode_increase(codegendata *cd, u1 *ncodeptr)
 #endif
 
 
 #endif
 
 
-void codegen_addreference(codegendata *cd, basicblock *target, void *branchptr)
-{
-       s4 branchpos;
-
-       branchpos = (u1 *) branchptr - cd->mcodebase;
-
-#if !defined(ENABLE_INTRP)
-       /* The interpreter uses absolute branches, so we do branch resolving */
-       /* after the code and data segment move. */
-
-       /* Check if the target basicblock has already a start pc, so the jump is  */
-       /* backward and we can resolve it immediately.                            */
-
-       if (target->mpc >= 0) {
-               gen_resolvebranch((u1 *) cd->mcodebase + branchpos,
-                                                 branchpos,
-                                                 target->mpc);
-
-       } else
-#endif
-       {
-               branchref *br = DNEW(branchref);
-
-               br->branchpos = branchpos;
-               br->next      = target->branchrefs;
-
-               target->branchrefs = br;
-       }
-}
+/* codegen_add_branch_ref ******************************************************
 
 
-
-/* codegen_addxboundrefs *******************************************************
-
-   Adds an ArrayIndexOutOfBoundsException branch to the list.
+   Prepends an branch to the list.
 
 *******************************************************************************/
 
 
 *******************************************************************************/
 
-void codegen_addxboundrefs(codegendata *cd, void *branchptr, s4 reg)
+void codegen_add_branch_ref(codegendata *cd, basicblock *target, s4 condition, s4 reg, u4 options)
 {
 {
-       s4 branchpos;
        branchref *br;
        branchref *br;
+       s4         branchmpc;
 
 
-       branchpos = (u1 *) branchptr - cd->mcodebase;
-
-       br = DNEW(branchref);
-
-       br->branchpos = branchpos;
-       br->reg       = reg;
-       br->next      = cd->xboundrefs;
-
-       cd->xboundrefs = br;
-}
-
-
-/* codegen_addxcastrefs ********************************************************
+       STATISTICS(count_branches_unresolved++);
 
 
-   Adds an ClassCastException branch to the list.
+       /* calculate the mpc of the branch instruction */
 
 
-*******************************************************************************/
-
-void codegen_addxcastrefs(codegendata *cd, void *branchptr)
-{
-       s4         branchpos;
-       branchref *br;
-
-       branchpos = (u1 *) branchptr - cd->mcodebase;
+       branchmpc = cd->mcodeptr - cd->mcodebase;
 
        br = DNEW(branchref);
 
 
        br = DNEW(branchref);
 
-       br->branchpos = branchpos;
-       br->next      = cd->xcastrefs;
+       br->branchmpc = branchmpc;
+       br->condition = condition;
+       br->reg       = reg;
+       br->options   = options;
+       br->next      = target->branchrefs;
 
 
-       cd->xcastrefs = br;
+       target->branchrefs = br;
 }
 
 
 }
 
 
-/* codegen_addxdivrefs *********************************************************
+/* codegen_resolve_branchrefs **************************************************
 
 
-   Adds an ArithmeticException branch to the list.
+   Resolves and patches the branch references of a given basic block.
 
 *******************************************************************************/
 
 
 *******************************************************************************/
 
-void codegen_addxdivrefs(codegendata *cd, void *branchptr)
+void codegen_resolve_branchrefs(codegendata *cd, basicblock *bptr)
 {
 {
-       s4         branchpos;
        branchref *br;
        branchref *br;
+       u1        *mcodeptr;
 
 
-       branchpos = (u1 *) branchptr - cd->mcodebase;
-
-       br = DNEW(branchref);
-
-       br->branchpos = branchpos;
-       br->next      = cd->xdivrefs;
-
-       cd->xdivrefs = br;
-}
+       /* 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;
 
 
-/* codegen_addxstorerefs *******************************************************
+       /* just to make sure */
 
 
-   Adds an ArrayStoreException branch to the list.
+       assert(bptr->mpc >= 0);
 
 
-*******************************************************************************/
+       for (br = bptr->branchrefs; br != NULL; br = br->next) {
+               /* temporary set the mcodeptr */
 
 
-void codegen_addxstorerefs(codegendata *cd, void *branchptr)
-{
-       s4         branchpos;
-       branchref *br;
+               cd->mcodeptr = cd->mcodebase + br->branchmpc;
 
 
-       branchpos = (u1 *) branchptr - cd->mcodebase;
+               /* emit_bccz and emit_branch emit the correct code, even if we
+                  pass condition == BRANCH_UNCONDITIONAL or reg == -1. */
 
 
-       br = DNEW(branchref);
+               emit_bccz(cd, bptr, br->condition, br->reg, br->options);
+       }
 
 
-       br->branchpos = branchpos;
-       br->next      = cd->xstorerefs;
+       /* restore mcodeptr */
 
 
-       cd->xstorerefs = br;
+       cd->mcodeptr = mcodeptr;
 }
 
 
 }
 
 
-/* codegen_addxnullrefs ********************************************************
+/* codegen_branch_label_add ****************************************************
 
 
-   Adds an NullPointerException branch to the list.
+   Append an branch to the label-branch list.
 
 *******************************************************************************/
 
 
 *******************************************************************************/
 
-void codegen_addxnullrefs(codegendata *cd, void *branchptr)
+void codegen_branch_label_add(codegendata *cd, s4 label, s4 condition, s4 reg, u4 options)
 {
 {
-       s4         branchpos;
-       branchref *br;
-
-       branchpos = (u1 *) branchptr - cd->mcodebase;
+       list_t             *list;
+       branch_label_ref_t *br;
+       s4                  mpc;
 
 
-       br = DNEW(branchref);
+       /* get the label list */
 
 
-       br->branchpos = branchpos;
-       br->next      = cd->xnullrefs;
-
-       cd->xnullrefs = br;
-}
-
-
-/* codegen_addxexceptionsrefs **************************************************
-
-   Adds an common exception branch to the list.
-
-*******************************************************************************/
+       list = cd->brancheslabel;
+       
+       /* calculate the current mpc */
 
 
-void codegen_addxexceptionrefs(codegendata *cd, void *branchptr)
-{
-       s4 branchpos;
-       branchref *br;
+       mpc = cd->mcodeptr - cd->mcodebase;
 
 
-       branchpos = (u1 *) branchptr - cd->mcodebase;
+       br = DNEW(branch_label_ref_t);
 
 
-       br = DNEW(branchref);
+       br->mpc       = mpc;
+       br->label     = label;
+       br->condition = condition;
+       br->reg       = reg;
+       br->options   = options;
 
 
-       br->branchpos = branchpos;
-       br->next      = cd->xexceptionrefs;
+       /* add the branch to the list */
 
 
-       cd->xexceptionrefs = br;
+       list_add_last_unsynced(list, br);
 }
 
 
 }
 
 
-/* codegen_addpatchref *********************************************************
+/* codegen_add_patch_ref *******************************************************
 
 
-   Adds a new patcher reference to the list of patching positions.
+   Appends a new patcher reference to the list of patching positions.
 
 *******************************************************************************/
 
 
 *******************************************************************************/
 
-void codegen_addpatchref(codegendata *cd, voidptr branchptr,
-                                                functionptr patcher, voidptr ref, s4 disp)
+void codegen_add_patch_ref(codegendata *cd, functionptr patcher, voidptr ref,
+                                                  s4 disp)
 {
        patchref *pr;
 {
        patchref *pr;
-       s4        branchpos;
+       s4        branchmpc;
 
 
-       branchpos = (u1 *) branchptr - cd->mcodebase;
+       branchmpc = cd->mcodeptr - cd->mcodebase;
 
        pr = DNEW(patchref);
 
 
        pr = DNEW(patchref);
 
-       pr->branchpos = branchpos;
+       pr->branchpos = branchmpc;
+       pr->disp      = disp;
        pr->patcher   = patcher;
        pr->ref       = ref;
        pr->patcher   = patcher;
        pr->ref       = ref;
-       pr->disp      = disp;
 
 
+/*     list_add_first(cd->patchrefs, pr); */
        pr->next      = cd->patchrefs;
        cd->patchrefs = pr;
 
        pr->next      = cd->patchrefs;
        cd->patchrefs = pr;
 
+       /* Generate NOPs for opt_shownops. */
+
+       if (opt_shownops)
+               PATCHER_NOPS;
+
 #if defined(ENABLE_JIT) && (defined(__I386__) || defined(__MIPS__) || defined(__X86_64__))
        /* On some architectures the patcher stub call instruction might
           be longer than the actual instruction generated.  On this
 #if defined(ENABLE_JIT) && (defined(__I386__) || defined(__MIPS__) || defined(__X86_64__))
        /* On some architectures the patcher stub call instruction might
           be longer than the actual instruction generated.  On this
@@ -530,15 +557,14 @@ void codegen_addpatchref(codegendata *cd, voidptr branchptr,
           the basic block code generation is completed, we check the
           range and maybe generate some nop's. */
 
           the basic block code generation is completed, we check the
           range and maybe generate some nop's. */
 
-       cd->lastmcodeptr = ((u1 *) branchptr) + PATCHER_CALL_SIZE;
+       cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
 #endif
 }
 
 
 #endif
 }
 
 
-#if defined(__I386__) || defined(__X86_64__) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
 /* methodtree_comparator *******************************************************
 
 /* methodtree_comparator *******************************************************
 
-   XXX
+   Comparator function used for the AVL tree of methods.
 
 *******************************************************************************/
 
 
 *******************************************************************************/
 
@@ -554,24 +580,34 @@ static s4 methodtree_comparator(const void *pc, const void *element)
           otherwise the avl_probe sometimes thinks the element is already in the
           tree */
 
           otherwise the avl_probe sometimes thinks the element is already in the
           tree */
 
-       if ((long) mte->startpc <= (long) mtepc->startpc &&
-               (long) mtepc->startpc <= (long) mte->endpc &&
-               (long) mte->startpc <= (long) mtepc->endpc &&
-               (long) mtepc->endpc <= (long) mte->endpc) {
+#ifdef __S390__
+       /* On S390 addresses are 31 bit. Compare only 31 bits of value.
+        */
+#      define ADDR_MASK(a) ((a) & 0x7FFFFFFF)
+#else
+#      define ADDR_MASK(a) (a)
+#endif
+
+       if (ADDR_MASK((long) mte->startpc) <= ADDR_MASK((long) mtepc->startpc) &&
+               ADDR_MASK((long) mtepc->startpc) <= ADDR_MASK((long) mte->endpc) &&
+               ADDR_MASK((long) mte->startpc) <= ADDR_MASK((long) mtepc->endpc) &&
+               ADDR_MASK((long) mtepc->endpc) <= ADDR_MASK((long) mte->endpc)) {
                return 0;
 
                return 0;
 
-       } else if ((long) mtepc->startpc < (long) mte->startpc) {
+       } else if (ADDR_MASK((long) mtepc->startpc) < ADDR_MASK((long) mte->startpc)) {
                return -1;
 
        } else {
                return 1;
        }
                return -1;
 
        } else {
                return 1;
        }
+
+#      undef ADDR_MASK
 }
 
 
 /* codegen_insertmethod ********************************************************
 
 }
 
 
 /* codegen_insertmethod ********************************************************
 
-   XXX
+   Insert the machine code range of a method into the AVL tree of methods.
 
 *******************************************************************************/
 
 
 *******************************************************************************/
 
@@ -593,13 +629,14 @@ void codegen_insertmethod(u1 *startpc, u1 *endpc)
 }
 
 
 }
 
 
-/* codegen_findmethod **********************************************************
+/* codegen_get_pv_from_pc ******************************************************
 
 
-   XXX
+   Find the PV for the given PC by searching in the AVL tree of
+   methods.
 
 *******************************************************************************/
 
 
 *******************************************************************************/
 
-u1 *codegen_findmethod(u1 *pc)
+u1 *codegen_get_pv_from_pc(u1 *pc)
 {
        methodtree_element  mtepc;
        methodtree_element *mte;
 {
        methodtree_element  mtepc;
        methodtree_element *mte;
@@ -611,17 +648,113 @@ u1 *codegen_findmethod(u1 *pc)
 
        mte = avl_find(methodtree, &mtepc);
 
 
        mte = avl_find(methodtree, &mtepc);
 
-       if (!mte) {
-               printf("Cannot find Java function at %p\n", (void *) (ptrint) pc);
-               assert(0);
+       if (mte == NULL) {
+               /* No method was found.  Let's dump a stacktrace. */
+
+#if defined(ENABLE_VMLOG)
+               vmlog_cacao_signl("SIGSEGV");
+#endif
+
+               log_println("We received a SIGSEGV and tried to handle it, but we were");
+               log_println("unable to find a Java method at:");
+               log_println("");
+#if SIZEOF_VOID_P == 8
+               log_println("PC=0x%016lx", pc);
+#else
+               log_println("PC=0x%08x", pc);
+#endif
+               log_println("");
+               log_println("Dumping the current stacktrace:");
+
+#if defined(ENABLE_THREADS)
+               /* XXX michi: This should be available even without threads! */
+               threads_print_stacktrace();
+#endif
 
 
-               throw_cacao_exception_exit(string_java_lang_InternalError,
-                                                                  "Cannot find Java function at %p", pc);
+               vm_abort("Exiting...");
        }
 
        return mte->startpc;
 }
        }
 
        return mte->startpc;
 }
-#endif /* defined(__I386__) || defined(__X86_64__) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
+
+
+/* codegen_get_pv_from_pc_nocheck **********************************************
+
+   Find the PV for the given PC by searching in the AVL tree of
+   methods.  This method does not check the return value and is used
+   by the profiler.
+
+*******************************************************************************/
+
+u1 *codegen_get_pv_from_pc_nocheck(u1 *pc)
+{
+       methodtree_element  mtepc;
+       methodtree_element *mte;
+
+       /* allocation of the search structure on the stack is much faster */
+
+       mtepc.startpc = pc;
+       mtepc.endpc   = pc;
+
+       mte = avl_find(methodtree, &mtepc);
+
+       if (mte == NULL)
+               return NULL;
+       else
+               return mte->startpc;
+}
+
+
+/* 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++;
+
+       /* XXX assert(cd->lastmcodeptr <= cd->mcodeptr); */
+
+       cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
+}
+#endif /* defined(ENABLE_REPLACEMENT) */
 
 
 /* codegen_finish **************************************************************
 
 
 /* codegen_finish **************************************************************
@@ -632,22 +765,37 @@ u1 *codegen_findmethod(u1 *pc)
 
 *******************************************************************************/
 
 
 *******************************************************************************/
 
-void codegen_finish(methodinfo *m, codegendata *cd, s4 mcodelen)
+void codegen_finish(jitdata *jd)
 {
 {
-#if 0
-       s4       mcodelen;
+       codeinfo    *code;
+       codegendata *cd;
+       s4           mcodelen;
+#if defined(ENABLE_INTRP)
+       s4           ncodelen;
 #endif
 #endif
+       s4           alignedmcodelen;
+       jumpref     *jr;
+       u1          *epoint;
+       s4           extralen;
+       s4           alignedlen;
+
+       /* get required compiler data */
+
+       code = jd->code;
+       cd   = jd->cd;
+
+       /* prevent compiler warning */
+
 #if defined(ENABLE_INTRP)
 #if defined(ENABLE_INTRP)
-       s4       ncodelen;
+       ncodelen = 0;
 #endif
 #endif
-       s4       alignedmcodelen;
-       jumpref *jr;
-       u1      *epoint;
-       s4       extralen;
-       s4       alignedlen;
-
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
-       extralen = sizeof(threadcritnode) * cd->threadcritcount;
+
+       /* calculate the code length */
+
+       mcodelen = (s4) (cd->mcodeptr - cd->mcodebase);
+
+#if defined(ENABLE_THREADS)
+       extralen = sizeof(critical_section_node_t) * cd->threadcritcount;
 #else
        extralen = 0;
 #endif
 #else
        extralen = 0;
 #endif
@@ -659,18 +807,17 @@ void codegen_finish(methodinfo *m, codegendata *cd, s4 mcodelen)
        }
 #endif
 
        }
 #endif
 
-#if 0
-       mcodelen = cd->mcodeptr - cd->mcodebase;
-#endif
-       alignedmcodelen = ALIGN(mcodelen, MAX_ALIGN);
+       alignedmcodelen = MEMORY_ALIGN(mcodelen, MAX_ALIGN);
 
 #if defined(ENABLE_INTRP)
 
 #if defined(ENABLE_INTRP)
-       if (opt_intrp) {
+       if (opt_intrp)
                ncodelen = cd->ncodeptr - cd->ncodebase;
                ncodelen = cd->ncodeptr - cd->ncodebase;
+       else {
+               ncodelen = 0; /* avoid compiler warning */
        }
 #endif
 
        }
 #endif
 
-       cd->dseglen = ALIGN(cd->dseglen, MAX_ALIGN);
+       cd->dseglen = MEMORY_ALIGN(cd->dseglen, MAX_ALIGN);
        alignedlen = alignedmcodelen + cd->dseglen;
 
 #if defined(ENABLE_INTRP)
        alignedlen = alignedmcodelen + cd->dseglen;
 
 #if defined(ENABLE_INTRP)
@@ -681,26 +828,37 @@ void codegen_finish(methodinfo *m, codegendata *cd, s4 mcodelen)
 
        /* allocate new memory */
 
 
        /* allocate new memory */
 
-       m->mcodelength = mcodelen + cd->dseglen;
-       m->mcode = CNEW(u1, alignedlen + extralen);
+       code->mcodelength = mcodelen + cd->dseglen;
+       code->mcode       = CNEW(u1, alignedlen + extralen);
 
 
-       /* copy data and code to their new location */
+       /* 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);
 
 
-       MCOPY((void *) m->mcode, cd->dsegtop - cd->dseglen, u1, cd->dseglen);
-       MCOPY((void *) (m->mcode + cd->dseglen), cd->mcodebase, u1, mcodelen);
+       /* copy code to the new location */
 
 
-       m->entrypoint = epoint = (m->mcode + cd->dseglen);
+       MCOPY((void *) code->entrypoint, cd->mcodebase, u1, mcodelen);
 
 #if defined(ENABLE_INTRP)
        /* relocate native dynamic superinstruction code (if any) */
 
        if (opt_intrp) {
 
 #if defined(ENABLE_INTRP)
        /* relocate native dynamic superinstruction code (if any) */
 
        if (opt_intrp) {
-               cd->mcodebase = m->entrypoint;
+               cd->mcodebase = code->entrypoint;
 
                if (ncodelen > 0) {
 
                if (ncodelen > 0) {
-                       u1 *ncodebase = m->mcode + cd->dseglen + alignedmcodelen;
-                       MCOPY((void *)ncodebase, cd->ncodebase, u1, ncodelen);
-                       /* XXX cacheflush((void *)ncodebase, ncodelen); */
+                       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;
                        /* set some cd variables for dynamic_super_rerwite */
 
                        cd->ncodebase = ncodebase;
@@ -723,11 +881,18 @@ void codegen_finish(methodinfo *m, codegendata *cd, s4 mcodelen)
        {
                linenumberref *lr;
                ptrint lrtlen = 0;
        {
                linenumberref *lr;
                ptrint lrtlen = 0;
+               ptrint target;
 
                for (lr = cd->linenumberreferences; lr != NULL; lr = lr->next) {
                        lrtlen++;
 
                for (lr = cd->linenumberreferences; lr != NULL; lr = lr->next) {
                        lrtlen++;
-                       *((functionptr *) ((ptrint) epoint + (ptrint) lr->tablepos)) =
-                               (functionptr) ((ptrint) epoint + (ptrint) lr->targetmpc);
+                       target = lr->targetmpc;
+                       /* if the entry contains an mcode pointer (normal case), resolve it */
+                       /* (see doc/inlining_stacktrace.txt for details)                    */
+                       if (lr->linenumber >= -2) {
+                           target += (ptrint) epoint;
+                       }
+                       *((functionptr *) ((ptrint) epoint + (ptrint) lr->tablepos)) = 
+                               (functionptr) target;
                }
                
                *((functionptr *) ((ptrint) epoint + cd->linenumbertablestartpos)) =
                }
                
                *((functionptr *) ((ptrint) epoint + cd->linenumbertablestartpos)) =
@@ -736,76 +901,188 @@ void codegen_finish(methodinfo *m, codegendata *cd, s4 mcodelen)
                *((ptrint *) ((ptrint) epoint + cd->linenumbertablesizepos)) = lrtlen;
        }
 
                *((ptrint *) ((ptrint) epoint + cd->linenumbertablesizepos)) = lrtlen;
        }
 
-#if defined(__I386__) || defined(__X86_64__) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
-       /* add method into methodtree to find the entrypoint */
+#if defined(ENABLE_REPLACEMENT)
+       /* replacement point resolving */
+       {
+               int i;
+               rplpoint *rp;
 
 
-       codegen_insertmethod(m->entrypoint, m->entrypoint + mcodelen);
-#endif
+               code->replacementstubs += (ptrint) epoint;
 
 
+               rp = code->rplpoints;
+               for (i=0; i<code->rplpointcount; ++i, ++rp) {
+                       rp->pc = (u1*) ((ptrint) epoint + (ptrint) rp->pc);
+               }
+       }
+#endif /* defined(ENABLE_REPLACEMENT) */
+
+       /* add method into methodtree to find the entrypoint */
+
+       codegen_insertmethod(code->entrypoint, code->entrypoint + mcodelen);
 
 
-#if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(ENABLE_INTRP)
+#if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
        /* resolve data segment references */
 
        /* resolve data segment references */
 
-       dseg_resolve_datareferences(cd, m);
+       dseg_resolve_datareferences(jd);
 #endif
 
 #endif
 
-
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+#if defined(ENABLE_THREADS)
        {
        {
-               threadcritnode *n = (threadcritnode *) ((ptrint) m->mcode + alignedlen);
+               critical_section_node_t *n = (critical_section_node_t *) ((ptrint) code->mcode + alignedlen);
                s4 i;
                s4 i;
-               threadcritnodetemp *nt = cd->threadcrit;
+               codegen_critical_section_t *nt = cd->threadcrit;
 
                for (i = 0; i < cd->threadcritcount; i++) {
 
                for (i = 0; i < cd->threadcritcount; i++) {
-                       n->mcodebegin = (u1 *) (ptrint) m->mcode + nt->mcodebegin;
-                       n->mcodeend = (u1 *) (ptrint) m->mcode + nt->mcodeend;
-                       n->mcoderestart = (u1 *) (ptrint) m->mcode + nt->mcoderestart;
-                       thread_registercritical(n);
+                       n->mcodebegin = (u1 *) (ptrint) code->mcode + nt->mcodebegin;
+                       n->mcodeend = (u1 *) (ptrint) code->mcode + nt->mcodeend;
+                       n->mcoderestart = (u1 *) (ptrint) code->mcode + nt->mcoderestart;
+                       critical_register_critical_section(n);
                        n++;
                        nt = nt->next;
                }
        }
 #endif
                        n++;
                        nt = nt->next;
                }
        }
 #endif
+
+       /* flush the instruction and data caches */
+
+       md_cacheflush(code->mcode, code->mcodelength);
 }
 
 
 }
 
 
-/* codegen_createnativestub ****************************************************
+/* codegen_generate_stub_compiler **********************************************
 
 
-   Wrapper for createnativestub.
+   Wrapper for codegen_emit_stub_compiler.
+
+   Returns:
+       pointer to the compiler stub code.
 
 *******************************************************************************/
 
 
 *******************************************************************************/
 
-u1 *codegen_createnativestub(functionptr f, methodinfo *m)
+u1 *codegen_generate_stub_compiler(methodinfo *m)
 {
 {
-       codegendata        *cd;
-       registerdata       *rd;
-       t_inlining_globals *id;
-       s4                  dumpsize;
-       methoddesc         *md;
-       methoddesc         *nmd;        
-       s4                  nativeparams;
+       jitdata     *jd;
+       codegendata *cd;
+       ptrint      *d;                     /* pointer to data memory             */
+       u1          *c;                     /* pointer to code memory             */
+       s4           dumpsize;
 
        /* mark dump memory */
 
        dumpsize = dump_size();
 
 
        /* mark dump memory */
 
        dumpsize = dump_size();
 
-       cd = DNEW(codegendata);
-       rd = DNEW(registerdata);
-       id = DNEW(t_inlining_globals);
+       /* allocate required data structures */
 
 
-       /* setup code generation stuff */
+       jd = DNEW(jitdata);
+
+       jd->m     = m;
+       jd->cd    = DNEW(codegendata);
+       jd->flags = 0;
+
+       /* get required compiler data */
+
+       cd = jd->cd;
+
+       /* 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). */
 
 
-       inlining_setup(m, id);
+       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);
+
+       /* release dump memory */
+
+       dump_release(dumpsize);
+
+       /* return native stub code */
+
+       return c;
+}
+
+
+/* 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;
+       s4           dumpsize;
+       methoddesc  *md;
+       methoddesc  *nmd;       
+       s4           nativeparams;
+
+       /* mark dump memory */
+
+       dumpsize = dump_size();
+
+       jd = DNEW(jitdata);
+
+       jd->m     = m;
+       jd->cd    = DNEW(codegendata);
+       jd->rd    = DNEW(registerdata);
+       jd->flags = 0;
+
+       /* Allocate codeinfo memory from the heap as we need to keep them. */
+
+       jd->code  = code_codeinfo_new(m); /* XXX check allocation */
+
+       /* get required compiler data */
+
+       code = jd->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
 
 #if defined(ENABLE_JIT)
 # if defined(ENABLE_INTRP)
        if (!opt_intrp)
 # endif
-               reg_setup(m, rd, id);
+               reg_setup(jd);
 #endif
 
 #endif
 
-       codegen_setup(m, cd, id);
-                                               
+       codegen_setup(jd);
+
        /* create new method descriptor with additional native parameters */
 
        md = m->parseddesc;
        /* create new method descriptor with additional native parameters */
 
        md = m->parseddesc;
@@ -831,7 +1108,9 @@ u1 *codegen_createnativestub(functionptr f, methodinfo *m)
 # if defined(ENABLE_INTRP)
        if (!opt_intrp)
 # endif
 # if defined(ENABLE_INTRP)
        if (!opt_intrp)
 # endif
-               md_param_alloc(nmd);
+               /* pre-allocate the arguments for the native ABI */
+
+               md_param_alloc_native(nmd);
 #endif
 
        /* generate the code */
 #endif
 
        /* generate the code */
@@ -839,39 +1118,47 @@ u1 *codegen_createnativestub(functionptr f, methodinfo *m)
 #if defined(ENABLE_JIT)
 # if defined(ENABLE_INTRP)
        if (opt_intrp)
 #if defined(ENABLE_JIT)
 # if defined(ENABLE_INTRP)
        if (opt_intrp)
-               m->entrypoint = intrp_createnativestub(f, m, cd, rd, nmd);
+               intrp_createnativestub(f, jd, nmd);
        else
 # endif
        else
 # endif
-               m->entrypoint = createnativestub(f, m, cd, rd, nmd);
+               codegen_emit_stub_native(jd, nmd, f);
 #else
 #else
-       m->entrypoint = intrp_createnativestub(f, m, cd, rd, nmd);
+       intrp_createnativestub(f, jd, nmd);
 #endif
 
 #if defined(ENABLE_STATISTICS)
        if (opt_stat)
 #endif
 
 #if defined(ENABLE_STATISTICS)
        if (opt_stat)
-               count_nstub_len += m->mcodelength;
+               count_nstub_len += code->mcodelength;
 #endif
 
 #endif
 
+       /* reallocate the memory and finish the code generation */
+
+       codegen_finish(jd);
+
+#if !defined(NDEBUG)
        /* disassemble native stub */
 
        if (opt_shownativestub) {
        /* disassemble native stub */
 
        if (opt_shownativestub) {
+#if defined(ENABLE_DISASSEMBLER)
                codegen_disassemble_nativestub(m,
                codegen_disassemble_nativestub(m,
-                                                                          (u1 *) (ptrint) m->entrypoint,
-                                                                          (u1 *) (ptrint) m->entrypoint + (m->mcodelength - cd->dseglen));
+                                                                          (u1 *) (ptrint) code->entrypoint,
+                                                                          (u1 *) (ptrint) code->entrypoint + (code->mcodelength - jd->cd->dseglen));
+#endif
 
                /* show data segment */
 
                if (opt_showddatasegment)
 
                /* show data segment */
 
                if (opt_showddatasegment)
-                       dseg_display(m, cd);
+                       dseg_display(jd);
        }
        }
+#endif /* !defined(NDEBUG) */
 
        /* release memory */
 
        dump_release(dumpsize);
 
 
        /* release memory */
 
        dump_release(dumpsize);
 
-       /* return native stub entry point */
+       /* return native stub code */
 
 
-       return m->entrypoint;
+       return code;
 }
 
 
 }
 
 
@@ -881,17 +1168,19 @@ u1 *codegen_createnativestub(functionptr f, methodinfo *m)
 
 *******************************************************************************/
 
 
 *******************************************************************************/
 
+#if defined(ENABLE_DISASSEMBLER)
 void codegen_disassemble_nativestub(methodinfo *m, u1 *start, u1 *end)
 {
        printf("Native stub: ");
 void codegen_disassemble_nativestub(methodinfo *m, u1 *start, u1 *end)
 {
        printf("Native stub: ");
-       utf_fprint_classname(stdout, m->class->name);
+       utf_fprint_printable_ascii_classname(stdout, m->class->name);
        printf(".");
        printf(".");
-       utf_fprint(stdout, m->name);
-       utf_fprint(stdout, m->descriptor);
+       utf_fprint_printable_ascii(stdout, m->name);
+       utf_fprint_printable_ascii(stdout, m->descriptor);
        printf("\n\nLength: %d\n\n", (s4) (end - start));
 
        DISASSEMBLE(start, end);
 }
        printf("\n\nLength: %d\n\n", (s4) (end - start));
 
        DISASSEMBLE(start, end);
 }
+#endif
 
 
 /* codegen_start_native_call ***************************************************
 
 
 /* codegen_start_native_call ***************************************************
@@ -936,6 +1225,7 @@ void codegen_start_native_call(u1 *datasp, u1 *pv, u1 *sp, u1 *ra)
 
        stacktrace_create_native_stackframeinfo(sfi, pv, sp, ra);
 
 
        stacktrace_create_native_stackframeinfo(sfi, pv, sp, ra);
 
+#if defined(ENABLE_JAVASE)
        /* add current JNI local references table to this thread */
 
        lrt->capacity    = LOCALREFTABLE_CAPACITY;
        /* add current JNI local references table to this thread */
 
        lrt->capacity    = LOCALREFTABLE_CAPACITY;
@@ -948,47 +1238,74 @@ void codegen_start_native_call(u1 *datasp, u1 *pv, u1 *sp, u1 *ra)
        MSET(lrt->refs, 0, java_objectheader*, LOCALREFTABLE_CAPACITY);
 
        LOCALREFTABLE = lrt;
        MSET(lrt->refs, 0, java_objectheader*, LOCALREFTABLE_CAPACITY);
 
        LOCALREFTABLE = lrt;
+#endif
 }
 
 
 /* codegen_finish_native_call **************************************************
 
    Removes the stuff required for a native (JNI) function call.
 }
 
 
 /* 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.
 
 *******************************************************************************/
 
 
 *******************************************************************************/
 
-void codegen_finish_native_call(u1 *datasp)
+java_objectheader *codegen_finish_native_call(u1 *datasp)
 {
 {
-       stackframeinfo  *sfi;
-       stackframeinfo **psfi;
-       localref_table  *lrt;
-       s4               localframes;
+       stackframeinfo     *sfi;
+       stackframeinfo    **psfi;
+#if defined(ENABLE_JAVASE)
+       localref_table     *lrt;
+       localref_table     *plrt;
+       s4                  localframes;
+#endif
+       java_objectheader  *e;
 
        /* get data structures from stack */
 
        sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
 
        /* get data structures from stack */
 
        sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
-       lrt = (localref_table *) (datasp - sizeof(stackframeinfo) - 
-                                                         sizeof(localref_table));
 
        /* remove current stackframeinfo from chain */
 
 
        /* remove current stackframeinfo from chain */
 
-       psfi = STACKFRAMEINFO;
+       psfi = &STACKFRAMEINFO;
 
        *psfi = sfi->prev;
 
 
        *psfi = sfi->prev;
 
+#if defined(ENABLE_JAVASE)
        /* release JNI local references tables for this thread */
 
        lrt = LOCALREFTABLE;
 
        /* release JNI local references tables for this thread */
 
        lrt = LOCALREFTABLE;
 
-       /* got through all current local frames */
+       /* release all current local frames */
 
        for (localframes = lrt->localframes; localframes >= 1; localframes--) {
 
        for (localframes = lrt->localframes; localframes >= 1; localframes--) {
-               lrt = lrt->prev;
+               /* get previous frame */
+
+               plrt = lrt->prev;
+
+               /* Clear all reference entries (only for tables allocated on
+                  the Java heap). */
+
+               if (localframes > 1)
+                       MSET(&lrt->refs[0], 0, java_objectheader*, lrt->capacity);
+
+               lrt->prev = NULL;
+
+               /* set new local references table */
+
+               lrt = plrt;
        }
 
        /* now store the previous local frames in the thread structure */
 
        LOCALREFTABLE = lrt;
        }
 
        /* now store the previous local frames in the thread structure */
 
        LOCALREFTABLE = lrt;
+#endif
+
+       /* get the exception and return it */
+
+       e = exceptions_get_and_clear_exception();
+
+       return e;
 }
 
 
 }
 
 
@@ -1020,7 +1337,7 @@ void removenativestub(u1 *stub)
 }
 
 
 }
 
 
-/* reg_of_var ******************************************************************
+/* 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
 
    This function determines a register, to which the result of an
    operation should go, when it is ultimatively intended to store the
@@ -1036,52 +1353,30 @@ void removenativestub(u1 *stub)
 
 *******************************************************************************/
 
 
 *******************************************************************************/
 
-s4 reg_of_var(registerdata *rd, stackptr v, s4 tempregnum)
+s4 codegen_reg_of_var(u2 opcode, varinfo *v, s4 tempregnum)
 {
 {
-       varinfo *var;
-
-       switch (v->varkind) {
-       case TEMPVAR:
-               if (!(v->flags & INMEMORY))
-                       return(v->regoff);
-               break;
-
-       case STACKVAR:
-               var = &(rd->interfaces[v->varnum][v->type]);
-               v->regoff = var->regoff;
-               if (!(var->flags & INMEMORY))
-                       return(var->regoff);
-               break;
-
-       case LOCALVAR:
-               var = &(rd->locals[v->varnum][v->type]);
-               v->regoff = var->regoff;
-               if (!(var->flags & INMEMORY)) {
-#if defined(__ARM__) && defined(__ARMEL__)
-                       if (IS_2_WORD_TYPE(v->type) && (GET_HIGH_REG(var->regoff) == REG_SPLIT))
-                               return(PACK_REGS(GET_LOW_REG(var->regoff), GET_HIGH_REG(tempregnum)));
-#endif
-#if defined(__ARM__) && defined(__ARMEB__)
-                       if (IS_2_WORD_TYPE(v->type) && (GET_LOW_REG(var->regoff) == REG_SPLIT))
-                               return(PACK_REGS(GET_LOW_REG(tempregnum), GET_HIGH_REG(var->regoff)));
+
+#if 0
+       /* Do we have to generate a conditional move?  Yes, then always
+          return the temporary register.  The real register is identified
+          during the store. */
+
+       if (opcode & ICMD_CONDITION_MASK)
+               return tempregnum;
 #endif
 #endif
-                       return(var->regoff);
-               }
-               break;
 
 
-       case ARGVAR:
-               if (!(v->flags & INMEMORY)) {
+       if (!(v->flags & INMEMORY)) {
 #if defined(__ARM__) && defined(__ARMEL__)
 #if defined(__ARM__) && defined(__ARMEL__)
-                       if (IS_2_WORD_TYPE(v->type) && (GET_HIGH_REG(v->regoff) == REG_SPLIT))
-                               return(PACK_REGS(GET_LOW_REG(v->regoff), GET_HIGH_REG(tempregnum)));
+               if (IS_2_WORD_TYPE(v->type) && (GET_HIGH_REG(v->vv.regoff) == REG_SPLIT))
+                       return PACK_REGS(GET_LOW_REG(v->vv.regoff),
+                                                        GET_HIGH_REG(tempregnum));
 #endif
 #if defined(__ARM__) && defined(__ARMEB__)
 #endif
 #if defined(__ARM__) && defined(__ARMEB__)
-                       if (IS_2_WORD_TYPE(v->type) && (GET_LOW_REG(v->regoff) == REG_SPLIT))
-                               return(PACK_REGS(GET_LOW_REG(tempregnum), GET_HIGH_REG(v->regoff)));
+               if (IS_2_WORD_TYPE(v->type) && (GET_LOW_REG(v->vv.regoff) == REG_SPLIT))
+                       return PACK_REGS(GET_LOW_REG(tempregnum),
+                                                        GET_HIGH_REG(v->vv.regoff));
 #endif
 #endif
-                       return(v->regoff);
-               }
-               break;
+               return v->vv.regoff;
        }
 
 #if defined(ENABLE_STATISTICS)
        }
 
 #if defined(ENABLE_STATISTICS)
@@ -1089,13 +1384,32 @@ s4 reg_of_var(registerdata *rd, stackptr v, s4 tempregnum)
                count_spills_read++;
 #endif
 
                count_spills_read++;
 #endif
 
-       v->flags |= INMEMORY;
-
        return tempregnum;
 }
 
        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.
+       
+   On ARM we have to check if a long/double variable is splitted
+   across reg/stack (HIGH_REG == REG_SPLIT). We return the actual
+   register of dst.var for LOW_REG and the tempregnum for HIGH_REG in such
+   cases.  (michi 2005/07/24)
+
+*******************************************************************************/
+
+s4 codegen_reg_of_dst(jitdata *jd, instruction *iptr, s4 tempregnum)
+{
+       return codegen_reg_of_var(iptr->opc, VAROP(iptr->dst), tempregnum);
+}
+
 
 
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+#if defined(ENABLE_THREADS)
 void codegen_threadcritrestart(codegendata *cd, int offset)
 {
        cd->threadcritcurrent.mcoderestart = offset;
 void codegen_threadcritrestart(codegendata *cd, int offset)
 {
        cd->threadcritcurrent.mcoderestart = offset;
@@ -1112,7 +1426,7 @@ void codegen_threadcritstop(codegendata *cd, int offset)
 {
        cd->threadcritcurrent.next = cd->threadcrit;
        cd->threadcritcurrent.mcodeend = offset;
 {
        cd->threadcritcurrent.next = cd->threadcrit;
        cd->threadcritcurrent.mcodeend = offset;
-       cd->threadcrit = DNEW(threadcritnodetemp);
+       cd->threadcrit = DNEW(codegen_critical_section_t);
        *(cd->threadcrit) = cd->threadcritcurrent;
        cd->threadcritcount++;
 }
        *(cd->threadcrit) = cd->threadcritcurrent;
        cd->threadcritcount++;
 }
@@ -1130,4 +1444,5 @@ void codegen_threadcritstop(codegendata *cd, int offset)
  * c-basic-offset: 4
  * tab-width: 4
  * End:
  * c-basic-offset: 4
  * tab-width: 4
  * End:
+ * vim:noexpandtab:sw=4:ts=4:
  */
  */