replace helper_* calls in the pathers with calls to resolve_*_eager
[cacao.git] / src / vm / jit / codegen.inc
index a2300e621348f624d2e5c61d010db077d0561045..b65d46647015a4f7ec3e2422688269f9c1fa1820 100644 (file)
@@ -1,10 +1,9 @@
-/* vm/jit/codegen.inc - architecture independent code generator
+/* src/vm/jit/codegen.inc - architecture independent code generator
 
-   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
-   Institut f. Computersprachen, TU Wien
-   R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser, M. Probst,
-   S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich,
-   J. Wenninger
+   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
 
    This file is part of CACAO.
 
@@ -29,6 +28,7 @@
             Andreas  Krall
 
    Changes: Christian Thalinger
+            Joseph Wenninger
 
    All functions assume the following code area / data area layout:
 
    memory. All functions writing values into the data area return the offset
    relative the begin of the code area (start of procedure).   
 
-   $Id: codegen.inc 1680 2004-12-04 12:02:08Z jowenn $
+   $Id: codegen.inc 3416 2005-10-12 13:20:53Z twisti $
 
 */
 
-#ifndef _CODEGEN_INC_H_
-#define _CODEGEN_INC_H_
 
+#include <assert.h>
 #include <string.h>
 
-#if !defined(STATIC_CLASSPATH)
-# include <dlfcn.h>
-#endif
+#include "config.h"
+#include "vm/types.h"
 
 #include "mm/memory.h"
 #include "toolbox/avl.h"
 #include "toolbox/logging.h"
+#include "native/jni.h"
 #include "native/native.h"
 
 #if defined(USE_THREADS)
 #endif
 
 #include "vm/exceptions.h"
+#include "vm/method.h"
 #include "vm/options.h"
 #include "vm/statistics.h"
 #include "vm/jit/codegen.inc.h"
+#include "vm/jit/disass.h"
+#include "vm/jit/jit.h"
+#include "vm/jit/stacktrace.h"
 
 
 /* in this tree we store all method addresses *********************************/
 
-#if defined(__I386__) || defined(__X86_64__)
+#if defined(__I386__) || defined(__X86_64__) || defined(__INTRP__)
 static struct avl_table *methodtree = NULL;
 static int methodtree_comparator(const void *pc, const void *element,
                                                                 void *param);
@@ -94,28 +97,37 @@ static int methodtree_comparator(const void *pc, const void *element,
 
 *******************************************************************************/
 
-void codegen_init()
+void codegen_init(void)
 {
-#if defined(__I386__) || defined(__X86_64__)
+#if defined(__I386__) || defined(__X86_64__) || defined(__INTRP__)
        /* this tree is global, not method specific */
+
        if (!methodtree) {
+#if !defined(__INTRP__)
                methodtree_element *mte;
+#endif
 
                methodtree = avl_create(methodtree_comparator, NULL, NULL);
 
+#if !defined(__INTRP__)
+               /* insert asm_calljavafunction */
+
                mte = NEW(methodtree_element);
 
                mte->startpc = (functionptr) asm_calljavafunction;
-               mte->endpc = (functionptr) ((long) asm_calljavafunction2 - 1);
+               mte->endpc = (functionptr) ((ptrint) asm_calljavafunction2 - 1);
 
                avl_insert(methodtree, mte);
 
+               /* insert asm_calljavafunction2 */
+
                mte = NEW(methodtree_element);
 
                mte->startpc = (functionptr) asm_calljavafunction2;
-               mte->endpc = (functionptr) ((long) asm_call_jit_compiler - 1);
+               mte->endpc = (functionptr) ((ptrint) asm_call_jit_compiler - 1);
 
                avl_insert(methodtree, mte);
+#endif /* !defined(__INTRP__) */
        }
 #endif
 }
@@ -129,10 +141,10 @@ void codegen_init()
 
 void codegen_setup(methodinfo *m, codegendata *cd, t_inlining_globals *id)
 {
-       cd->mcodebase = MNEW(u1, MCODEINITSIZE);
+       cd->mcodebase = DMNEW(u1, MCODEINITSIZE);
        cd->mcodesize = MCODEINITSIZE;
        
-       cd->dsegtop = MNEW(u1, DSEGINITSIZE);
+       cd->dsegtop = DMNEW(u1, DSEGINITSIZE);
        cd->dsegsize = DSEGINITSIZE;
        cd->dsegtop += cd->dsegsize;
        cd->dseglen = 0;
@@ -140,12 +152,12 @@ void codegen_setup(methodinfo *m, codegendata *cd, t_inlining_globals *id)
        cd->jumpreferences = NULL;
        cd->datareferences = NULL;
        cd->xboundrefs = NULL;
-       cd->xcheckarefs = NULL;
        cd->xnullrefs = NULL;
        cd->xcastrefs = NULL;
+       cd->xstorerefs = NULL;
        cd->xdivrefs = NULL;
        cd->xexceptionrefs = NULL;
-       cd->clinitrefs = NULL;
+       cd->patchrefs = NULL;
 
        cd->linenumberreferences = NULL;
        cd->linenumbertablesizepos = 0;
@@ -159,12 +171,13 @@ void codegen_setup(methodinfo *m, codegendata *cd, t_inlining_globals *id)
        if (useinlining && id) {
                if (id->cumextablelength > 0) {
                        cd->exceptiontablelength = id->cumextablelength;
-                       cd->exceptiontable  = DMNEW(exceptiontable, id->cumextablelength + 1);
+                       cd->exceptiontable =
+                               DMNEW(exceptiontable, id->cumextablelength + 1);
                }
 
-       } else if (id && (id->method->exceptiontablelength >0)) {
+       } else if (id && (id->method->exceptiontablelength > 0)) {
                cd->exceptiontablelength = m->exceptiontablelength;
-               cd->exceptiontable  = DMNEW(exceptiontable, m->exceptiontablelength + 1);
+               cd->exceptiontable = DMNEW(exceptiontable, m->exceptiontablelength + 1);
        }
 
        if (id) {
@@ -184,22 +197,14 @@ void codegen_setup(methodinfo *m, codegendata *cd, t_inlining_globals *id)
 
 /* codegen_free ****************************************************************
 
-   releases temporary code and data area
+   Releases temporary code and data area.
 
 *******************************************************************************/
 
 void codegen_free(methodinfo *m, codegendata *cd)
 {
-       if (cd) {
 #if 0
-               if (cd->exceptiontablelength) {
-                       cd->exceptiontablelength = m->exceptiontablelength;
-                       MFREE(cd->exceptiontable, exceptiontable, cd->exceptiontablelength + 1);
-                       cd->exceptiontable = 0;
-                       cd->exceptiontablelength = 0;
-               }
-#endif
-
+       if (cd) {
                if (cd->mcodebase) {
                        MFREE(cd->mcodebase, u1, cd->mcodesize);
                        cd->mcodebase = NULL;
@@ -210,6 +215,7 @@ void codegen_free(methodinfo *m, codegendata *cd)
                        cd->dsegtop = NULL;
                }
        }
+#endif
 }
 
 
@@ -219,7 +225,7 @@ void codegen_free(methodinfo *m, codegendata *cd)
 
 *******************************************************************************/
 
-void codegen_close()
+void codegen_close(void)
 {
        /* TODO: release avl tree on i386 and x86_64 */
 }
@@ -232,10 +238,10 @@ static s4 *codegen_increase(codegendata *cd, u1 *codeptr)
        long len;
 
        len = codeptr - cd->mcodebase;
-       cd->mcodebase = MREALLOC(cd->mcodebase,
-                                                        u1,
-                                                        cd->mcodesize,
-                                                        cd->mcodesize * 2);
+       cd->mcodebase = DMREALLOC(cd->mcodebase,
+                                                         u1,
+                                                         cd->mcodesize,
+                                                         cd->mcodesize * 2);
        cd->mcodesize *= 2;
        cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
 
@@ -249,10 +255,10 @@ static void dseg_increase(codegendata *cd)
 {
        u1 *newstorage;
 
-       newstorage = MNEW(u1, cd->dsegsize * 2);
+       newstorage = DMNEW(u1, cd->dsegsize * 2);
 
-       memcpy(newstorage + cd->dsegsize, cd->dsegtop - cd->dsegsize, cd->dsegsize);
-       MFREE(cd->dsegtop - cd->dsegsize, u1, cd->dsegsize);
+       MCOPY(newstorage + cd->dsegsize, cd->dsegtop - cd->dsegsize, u1,
+                 cd->dsegsize);
 
        cd->dsegtop = newstorage;
        cd->dsegsize *= 2;
@@ -286,7 +292,7 @@ static s4 dseg_adds4(codegendata *cd, s4 value)
 }
 
 
-#if !defined(__I386__)
+#if !defined(__I386__) && !defined(__POWERPC__)
 static s4 dseg_adds8_increase(codegendata *cd, s8 value)
 {
        dseg_increase(cd);
@@ -314,6 +320,7 @@ static s4 dseg_adds8(codegendata *cd, s8 value)
 #endif
 
 
+#if !defined(__XDSPCORE__)
 static s4 dseg_addfloat_increase(codegendata *cd, float value)
 {
        dseg_increase(cd);
@@ -364,6 +371,7 @@ static s4 dseg_adddouble(codegendata *cd, double value)
 
        return -(cd->dseglen);
 }
+#endif /* !defined(__XDSPCORE__) */
 
 
 static void dseg_addtarget(codegendata *cd, basicblock *target)
@@ -378,6 +386,7 @@ static void dseg_addtarget(codegendata *cd, basicblock *target)
 }
 
 
+#if defined(__I386__) || defined(__X86_64__)
 static void dseg_adddata(codegendata *cd, u1 *ptr)
 {
        dataref *dr;
@@ -387,18 +396,30 @@ static void dseg_adddata(codegendata *cd, u1 *ptr)
        dr->next = cd->datareferences;
        cd->datareferences = dr;
 }
+#endif
+
 
+/* dseg_addlinenumbertablesize *************************************************
+
+   XXX
+
+*******************************************************************************/
 
 static void dseg_addlinenumbertablesize(codegendata *cd)
 {
-#ifdef __ALPHA__
-       dseg_adds4(cd, 0); /*PADDING*/
+#if defined (__ALPHA__) || defined(__MIPS__) || defined (__X86_64__)
+       /* 4-byte ALIGNMENT PADDING */
+
+       dseg_adds4(cd, 0);
 #endif
-       cd->linenumbertablesizepos = dseg_addaddress(cd, NULL); /*it could be considered to use adds4 here, to avoid 1 double word padding on ALPHA */
 
+       cd->linenumbertablesizepos = dseg_addaddress(cd, NULL);
        cd->linenumbertablestartpos = dseg_addaddress(cd, NULL);
-#ifdef __ALPHA__
-       dseg_adds4(cd, 0); /*PADDING*/
+
+#if defined(__ALPHA__) || defined(__MIPS__) || defined (__X86_64__)
+       /* 4-byte ALIGNMENT PADDING */
+
+       dseg_adds4(cd, 0);
 #endif
 }
 
@@ -429,12 +450,21 @@ static void codegen_addreference(codegendata *cd, basicblock *target, void *bran
 
        branchpos = (u1 *) branchptr - cd->mcodebase;
 
+#if !defined(__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 {
+       } else
+#endif
+       {
                branchref *br = DNEW(branchref);
 
                br->branchpos = branchpos;
@@ -459,7 +489,7 @@ static void codegen_addxboundrefs(codegendata *cd, void *branchptr, s4 reg)
 }
 
 
-static void codegen_addxcheckarefs(codegendata *cd, void *branchptr)
+static void codegen_addxnullrefs(codegendata *cd, void *branchptr)
 {
        s4 branchpos;
        branchref *br;
@@ -468,12 +498,12 @@ static void codegen_addxcheckarefs(codegendata *cd, void *branchptr)
 
        br = DNEW(branchref);
        br->branchpos = branchpos;
-       br->next = cd->xcheckarefs;
-       cd->xcheckarefs = br;
+       br->next = cd->xnullrefs;
+       cd->xnullrefs = br;
 }
 
 
-static void codegen_addxnullrefs(codegendata *cd, void *branchptr)
+static void codegen_addxcastrefs(codegendata *cd, void *branchptr)
 {
        s4 branchpos;
        branchref *br;
@@ -482,26 +512,38 @@ static void codegen_addxnullrefs(codegendata *cd, void *branchptr)
 
        br = DNEW(branchref);
        br->branchpos = branchpos;
-       br->next = cd->xnullrefs;
-       cd->xnullrefs = br;
+       br->next = cd->xcastrefs;
+       cd->xcastrefs = br;
 }
 
 
-static void codegen_addxcastrefs(codegendata *cd, void *branchptr)
+/* codegen_addxstorerefs *******************************************************
+
+   Adds an ArrayStoreException branch to the list.
+
+*******************************************************************************/
+
+static void codegen_addxstorerefs(codegendata *cd, void *branchptr)
 {
-       s4 branchpos;
+       s4         branchpos;
        branchref *br;
 
        branchpos = (u1 *) branchptr - cd->mcodebase;
 
        br = DNEW(branchref);
        br->branchpos = branchpos;
-       br->next = cd->xcastrefs;
-       cd->xcastrefs = br;
+       br->next = cd->xstorerefs;
+       cd->xstorerefs = br;
 }
 
 
-static void codegen_addxexceptionrefs(codegendata *cd, void *branchptr)
+/* codegen_addxdivrefs *********************************************************
+
+   Adds an ArithmeticException branch to the list.
+
+*******************************************************************************/
+
+static void codegen_addxdivrefs(codegendata *cd, void *branchptr)
 {
        s4 branchpos;
        branchref *br;
@@ -510,13 +552,12 @@ static void codegen_addxexceptionrefs(codegendata *cd, void *branchptr)
 
        br = DNEW(branchref);
        br->branchpos = branchpos;
-       br->next = cd->xexceptionrefs;
-       cd->xexceptionrefs = br;
+       br->next = cd->xdivrefs;
+       cd->xdivrefs = br;
 }
 
 
-#if defined(__I386__) || defined(__X86_64__)
-static void codegen_addxdivrefs(codegendata *cd, void *branchptr)
+static void codegen_addxexceptionrefs(codegendata *cd, void *branchptr)
 {
        s4 branchpos;
        branchref *br;
@@ -525,32 +566,46 @@ static void codegen_addxdivrefs(codegendata *cd, void *branchptr)
 
        br = DNEW(branchref);
        br->branchpos = branchpos;
-       br->next = cd->xdivrefs;
-       cd->xdivrefs = br;
+       br->next = cd->xexceptionrefs;
+       cd->xexceptionrefs = br;
 }
-#endif
 
 
-static void codegen_addclinitref(codegendata *cd,
-                                                                void *branchptr,
-                                                                classinfo *class)
+/* codegen_addpatchref *********************************************************
+
+   Adds a new patcher reference to the list of patching positions.
+
+*******************************************************************************/
+
+static void codegen_addpatchref(codegendata *cd, voidptr branchptr,
+                                                               functionptr patcher, voidptr ref, s4 disp)
 {
-       s4 branchpos;
-       clinitref *cr;
+       patchref *pr;
+       s4        branchpos;
 
        branchpos = (u1 *) branchptr - cd->mcodebase;
 
-       cr = DNEW(clinitref);
-       cr->branchpos = branchpos;
-       cr->class = class;
-       cr->next = cd->clinitrefs;
-       cd->clinitrefs = cr;
+       pr = DNEW(patchref);
+
+       pr->branchpos = branchpos;
+       pr->patcher   = patcher;
+       pr->ref       = ref;
+       pr->disp      = disp;
+
+       pr->next      = cd->patchrefs;
+       cd->patchrefs = pr;
 }
 
 
+/* codegen_createlinenumbertable ***********************************************
+
+   Creates a line number table in the data segment from the created
+   entries in linenumberreferences.
+
+*******************************************************************************/
+
 static void codegen_createlinenumbertable(codegendata *cd)
 {
-#ifdef __I386__
        linenumberref *lr;
 
        for (lr = cd->linenumberreferences; lr != NULL; lr = lr->next) {
@@ -561,11 +616,16 @@ static void codegen_createlinenumbertable(codegendata *cd)
 
                dseg_addaddress(cd, lr->linenumber);
        }
-#endif
 }
 
 
-#if defined(__I386__) || defined(__X86_64__)
+#if defined(__I386__) || defined(__X86_64__) || defined(__INTRP__)
+/* methodtree_comparator *******************************************************
+
+   XXX
+
+*******************************************************************************/
+
 static int methodtree_comparator(const void *pc, const void *element, void *param)
 {
        methodtree_element *mte;
@@ -577,6 +637,7 @@ static int methodtree_comparator(const void *pc, const void *element, void *para
        /* compare both startpc and endpc of pc, even if they have the same value,
           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 &&
@@ -592,22 +653,11 @@ static int methodtree_comparator(const void *pc, const void *element, void *para
 }
 
 
-#if 0
-void *codegen_findmethod1(void *pc)
-{
-       void * retVal=findmethod(pc);
-       methodinfo **ma=(methodinfo**)retVal;
-       methodinfo *m=ma[-1];
-       if (m)
-               if (m->name)
-                       utf_display(m->name);
-               else 
-                       log_text("No Name");
-       else log_text("No methodinfo");
-       return retVal;
-}
-#endif
+/* codegen_insertmethod ********************************************************
+
+   XXX
 
+*******************************************************************************/
 
 void codegen_insertmethod(functionptr startpc, functionptr endpc)
 {
@@ -629,6 +679,7 @@ void codegen_insertmethod(functionptr startpc, functionptr endpc)
                tables_unlock();
 #endif
 #endif
+               assert(0);
                throw_cacao_exception_exit(string_java_lang_InternalError,
                                                                   "duplicate entry");
        }
@@ -641,6 +692,12 @@ void codegen_insertmethod(functionptr startpc, functionptr endpc)
 }
 
 
+/* codegen_findmethod **********************************************************
+
+   XXX
+
+*******************************************************************************/
+
 functionptr codegen_findmethod(functionptr pc)
 {
        methodtree_element *mtepc;
@@ -666,8 +723,10 @@ functionptr codegen_findmethod(functionptr pc)
                tables_unlock();
 #endif
 #endif
+               printf("Cannot find Java function at %p\n", (void *) (ptrint) pc);
+               assert(0);
                throw_cacao_exception_exit(string_java_lang_InternalError,
-                                                                  "cannot find function");
+                                                                  "Cannot find Java function at %p", pc);
        }
 
 #if defined(USE_THREADS)
@@ -678,15 +737,23 @@ functionptr codegen_findmethod(functionptr pc)
 
        return mte->startpc;
 }
-#endif
+#endif /* defined(__I386__) || defined(__X86_64__) || defined(__INTRP__) */
 
 
+/* 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, ...
+
+*******************************************************************************/
+
 static void codegen_finish(methodinfo *m, codegendata *cd, s4 mcodelen)
 {
-       jumpref *jr;
-       functionptr epoint;
-       s4 extralen;
-       s4 alignedlen;
+       jumpref     *jr;
+       functionptr  epoint;
+       s4           extralen;
+       s4           alignedlen;
 
 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
        extralen = sizeof(threadcritnode) * cd->threadcritcount;
@@ -704,61 +771,63 @@ static void codegen_finish(methodinfo *m, codegendata *cd, s4 mcodelen)
        cd->dseglen = ALIGN(cd->dseglen, MAX_ALIGN);
        alignedlen = ALIGN(mcodelen, MAX_ALIGN) + cd->dseglen;
 
+       /* allocate new memory */
+
        m->mcodelength = mcodelen + cd->dseglen;
-       m->mcode = (functionptr) (long) CNEW(u1, alignedlen + extralen);
+       m->mcode = (functionptr) (ptrint) CNEW(u1, alignedlen + extralen);
 
-       memcpy((void *) (long) m->mcode, cd->dsegtop - cd->dseglen, cd->dseglen);
-       memcpy((void *) ((long) m->mcode + cd->dseglen), cd->mcodebase, mcodelen);
+       /* copy data and code to their new location */
 
-       m->entrypoint = epoint = (functionptr) ((long) m->mcode + cd->dseglen);
+       MCOPY((void *) (ptrint) m->mcode, cd->dsegtop - cd->dseglen, u1,
+                 cd->dseglen);
+       MCOPY((void *) ((ptrint) m->mcode + cd->dseglen), cd->mcodebase, u1,
+                 mcodelen);
+
+       m->entrypoint = epoint = (functionptr) ((ptrint) m->mcode + cd->dseglen);
 
        /* jump table resolving */
+
        jr = cd->jumpreferences;
        while (jr != NULL) {
-               *((functionptr *) ((long) epoint + jr->tablepos)) =
-                       (functionptr) ((long) epoint + (long) jr->target->mpc);
+               *((functionptr *) ((ptrint) epoint + jr->tablepos)) =
+                       (functionptr) ((ptrint) epoint + (ptrint) jr->target->mpc);
                jr = jr->next;
        }
 
-#ifdef __I386__
        /* line number table resolving */
        {
                linenumberref *lr;
-#if POINTERSIZE == 8
-               s8 lrtlen = 0;
-#else
-               s4 lrtlen = 0;
-#endif
+               ptrint lrtlen = 0;
 
                for (lr = cd->linenumberreferences; lr != NULL; lr = lr->next) {
                        lrtlen++;
-                       *((functionptr *) ((long) epoint + (long) lr->tablepos)) =
-                               (functionptr) ((long) epoint + (long) lr->targetmpc);
+                       *((functionptr *) ((ptrint) epoint + (ptrint) lr->tablepos)) =
+                               (functionptr) ((ptrint) epoint + (ptrint) lr->targetmpc);
                }
                
-               *((functionptr *) ((long) epoint + cd->linenumbertablestartpos)) =
-                       (functionptr) ((long) epoint + cd->linenumbertab);
-#if POINTERSIZE == 8
-               *((s8 *) ((s8) epoint + cd->linenumbertablesizepos)) = lrtlen;
-#else
-               *((s4 *) ((s4) epoint + cd->linenumbertablesizepos)) = lrtlen;
-#endif
+               *((functionptr *) ((ptrint) epoint + cd->linenumbertablestartpos)) =
+                       (functionptr) ((ptrint) epoint + cd->linenumbertab);
+
+               *((ptrint *) ((ptrint) epoint + cd->linenumbertablesizepos)) = lrtlen;
        }
+
+#if defined(__I386__) || defined(__X86_64__) || defined(__INTRP__)
+       /* add method into methodtree to find the entrypoint */
+
+       codegen_insertmethod(m->entrypoint,
+                                                (functionptr) ((ptrint) m->entrypoint + mcodelen));
 #endif
 
-#if defined(__I386__) || defined(__X86_64__)
+#if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__)
        {
                dataref *dr;
 
-               /* add method into methodtree to find the entrypoint */
-               codegen_insertmethod(m->entrypoint,
-                                                        (functionptr) ((long) m->entrypoint + mcodelen));
-
                /* data segment references resolving */
+
                dr = cd->datareferences;
                while (dr != NULL) {
-                       *((functionptr *) ((long) epoint + (long) dr->pos - POINTERSIZE)) =
-                               epoint;
+                       *((functionptr *) ((ptrint) epoint + (ptrint) dr->pos -
+                                                          SIZEOF_VOID_P)) = epoint;
                        dr = dr->next;
                }
        }
@@ -766,14 +835,14 @@ static void codegen_finish(methodinfo *m, codegendata *cd, s4 mcodelen)
 
 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
        {
-               threadcritnode *n = (threadcritnode *) ((long) m->mcode + alignedlen);
+               threadcritnode *n = (threadcritnode *) ((ptrint) m->mcode + alignedlen);
                s4 i;
                threadcritnodetemp *nt = cd->threadcrit;
 
                for (i = 0; i < cd->threadcritcount; i++) {
-                       n->mcodebegin = (u1 *) (long) m->mcode + nt->mcodebegin;
-                       n->mcodeend = (u1 *) (long) m->mcode + nt->mcodeend;
-                       n->mcoderestart = (u1 *) (long) m->mcode + nt->mcoderestart;
+                       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++;
                        nt = nt->next;
@@ -788,16 +857,264 @@ void dseg_display(methodinfo *m, codegendata *cd)
        s4 *s4ptr;
        s4 i;
        
-       s4ptr = (s4 *) (long) m->mcode;
+       s4ptr = (s4 *) (ptrint) m->mcode;
 
        printf("  --- dump of datasegment\n");
        for (i = cd->dseglen; i > 0 ; i -= 4) {
-               printf("-%6x: %8x\n", i, (s4) (*s4ptr++));
+#if SIZEOF_VOID_P == 8
+               printf("0x%016lx:   -%6x (%6d): %8x\n",
+                          (ptrint) s4ptr, i, i, (s4) *s4ptr);
+#else
+               printf("0x%08x:   -%6x (%6d): %8x\n",
+                          (ptrint) s4ptr, i, i, (s4) *s4ptr);
+#endif
+               s4ptr++;
        }
+
        printf("  --- begin of data segment: %p\n", (void *) s4ptr);
 }
 
 
+
+/* codegen_createnativestub ****************************************************
+
+   Wrapper for createnativestub.
+
+*******************************************************************************/
+
+functionptr codegen_createnativestub(functionptr f, methodinfo *m)
+{
+       codegendata        *cd;
+       registerdata       *rd;
+       t_inlining_globals *id;
+       s4                  dumpsize;
+       methoddesc         *md;
+       methoddesc         *nmd;        
+       s4                  nativeparams;
+
+       /* mark dump memory */
+
+       dumpsize = dump_size();
+
+       cd = DNEW(codegendata);
+       rd = DNEW(registerdata);
+       id = DNEW(t_inlining_globals);
+
+       /* setup code generation stuff */
+
+       inlining_setup(m, id);
+#if !defined(__INTRP__)
+       reg_setup(m, rd, id);
+#endif
+       codegen_setup(m, cd, id);
+                                               
+       /* create new method descriptor with additional native parameters */
+
+       md = m->parseddesc;
+       nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
+       
+       nmd = (methoddesc *) DMNEW(u1, sizeof(methoddesc) - sizeof(typedesc) +
+                                                          md->paramcount * sizeof(typedesc) +
+                                                          nativeparams * sizeof(typedesc));
+
+       nmd->paramcount = md->paramcount + nativeparams;
+
+       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 + nativeparams, md->paramtypes, typedesc,
+                 md->paramcount);
+
+       md_param_alloc(nmd);
+
+       /* generate the code */
+
+       m->entrypoint = createnativestub(f, m, cd, rd, nmd);
+
+#if defined(STATISTICS)
+       if (opt_stat)
+               count_nstub_len += m->mcodelength;
+#endif
+
+       /* disassemble native stub */
+
+       if (opt_shownativestub) {
+               codegen_disassemble_nativestub(m,
+                                                                          (u1 *) (ptrint) m->entrypoint,
+                                                                          (u1 *) (ptrint) m->entrypoint + (m->mcodelength - cd->dseglen));
+
+               /* show data segment */
+
+               if (opt_showddatasegment)
+                       dseg_display(m, cd);
+       }
+
+       /* release memory */
+
+       dump_release(dumpsize);
+
+       /* return native stub entry point */
+
+       return m->entrypoint;
+}
+
+
+/* codegen_disassemble_nativestub **********************************************
+
+   Disassembles the generated native stub.
+
+*******************************************************************************/
+
+void codegen_disassemble_nativestub(methodinfo *m, u1 *start, u1 *end)
+{
+       printf("Native stub: ");
+       utf_fprint_classname(stdout, m->class->name);
+       printf(".");
+       utf_fprint(stdout, m->name);
+       utf_fprint(stdout, m->descriptor);
+       printf("\n\nLength: %d\n\n", (s4) (end - start));
+
+       disassemble(start, end);
+}
+
+
+/* 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:
+
+   +---------------------------+ <- SP (of parent Java function)
+   | return address            |
+   +---------------------------+
+   |                           |
+   | stackframe info structure |
+   |                           |
+   +---------------------------+
+   |                           |
+   | local references table    |
+   |                           |
+   +---------------------------+
+   |                           |
+   | arguments (if any)        |
+   |                           |
+   +---------------------------+ <- SP (native stub)
+
+*******************************************************************************/
+
+void codegen_start_native_call(u1 *datasp, u1 *pv, u1 *sp, functionptr ra)
+{
+       stackframeinfo *sfi;
+       localref_table *lrt;
+       nativethread   *info;
+
+       /* get data structures from stack */
+
+       sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
+       lrt = (localref_table *) (datasp - sizeof(stackframeinfo) - 
+                                                         sizeof(localref_table));
+
+       /* get thread info */
+
+       info = THREADINFO;
+
+       /* add a stackframeinfo to the chain */
+
+       stacktrace_create_native_stackframeinfo(sfi, pv, sp, ra);
+
+       /* add current JNI local references table to this thread */
+
+       lrt->capacity    = LOCALREFTABLE_CAPACITY;
+       lrt->used        = 0;
+       lrt->localframes = 1;
+       lrt->prev        = info->_localref_table;
+
+       /* clear the references array (memset is faster the a for-loop) */
+
+       MSET(lrt->refs, 0, java_objectheader*, LOCALREFTABLE_CAPACITY);
+
+       info->_localref_table = lrt;
+}
+
+
+/* codegen_finish_native_call **************************************************
+
+   Removes the stuff required for a native (JNI) function call.
+
+*******************************************************************************/
+
+void codegen_finish_native_call(u1 *datasp)
+{
+       stackframeinfo *sfi;
+       localref_table *lrt;
+       nativethread   *info;
+       s4              localframes;
+
+       /* get data structures from stack */
+
+       sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
+       lrt = (localref_table *) (datasp - sizeof(stackframeinfo) - 
+                                                         sizeof(localref_table));
+
+       /* get thread info */
+
+       info = THREADINFO;
+
+       /* remove current stackframeinfo from chain */
+
+       info->_stackframeinfo = sfi->prev;
+
+       /* release JNI local references tables for this thread */
+
+       lrt = info->_localref_table;
+
+       /* got through all current local frames */
+
+       for (localframes = lrt->localframes; localframes >= 1; localframes--) {
+               lrt = lrt->prev;
+       }
+
+       /* now store the previous local frames in the thread structure */
+
+       info->_localref_table = lrt;
+}
+
+
+/* removecompilerstub **********************************************************
+
+   Deletes a compilerstub from memory (simply by freeing it).
+
+*******************************************************************************/
+
+void removecompilerstub(functionptr stub)
+{
+       /* pass size 1 to keep the intern function happy */
+
+       CFREE((void *) (ptrint) stub, 1);
+}
+
+
+/* removenativestub ************************************************************
+
+   Removes a previously created native-stub from memory.
+    
+*******************************************************************************/
+
+void removenativestub(functionptr stub)
+{
+       /* pass size 1 to keep the intern function happy */
+
+       CFREE((void *) (ptrint) stub, 1);
+}
+
+
 /* 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
@@ -806,6 +1123,11 @@ void dseg_display(methodinfo *m, codegendata *cd)
     Otherwise (when v 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 v for LOW_REG and the tempregnum for HIGH_REG in such cases.
+    (michi 2005/07/24)
+*/
 
 static int reg_of_var(registerdata *rd, stackptr v, int tempregnum)
 {
@@ -816,43 +1138,48 @@ static int reg_of_var(registerdata *rd, stackptr v, int tempregnum)
                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 (!(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)));
+#endif
                        return(var->regoff);
+               }
                break;
+
        case ARGVAR:
-               v->regoff = v->varnum;
-               if (IS_FLT_DBL_TYPE(v->type)) {
-                       if (v->varnum < rd->fltreg_argnum) {
-                               v->regoff = rd->argfltregs[v->varnum];
-                               return(rd->argfltregs[v->varnum]);
-                       }
-
-               } else {
-#if defined(__POWERPC__)
-                       if (v->varnum < rd->intreg_argnum - (IS_2_WORD_TYPE(v->type) != 0)) {
-#else
-                       if (v->varnum < rd->intreg_argnum) {
+               if (!(v->flags & INMEMORY)) {
+#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)));
 #endif
-                               v->regoff = rd->argintregs[v->varnum];
-                               return (rd->argintregs[v->varnum]);
-                       }
-               }
-#if defined(__POWERPC__)
-               v->regoff += 6;
-#else
-               v->regoff -= rd->intreg_argnum;
+#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)));
 #endif
+                       return(v->regoff);
+               }
                break;
        }
+#ifdef STATISTICS
+       if (opt_stat)
+               count_spills_read++;
+#endif
        v->flags |= INMEMORY;
        return tempregnum;
 }
@@ -882,187 +1209,6 @@ static void codegen_threadcritstop(codegendata *cd, int offset)
 #endif
 
 
-#ifndef STATIC_CLASSPATH
-static size_t codegen_overloadPartLen(utf *desc) {
-        char *utf_ptr=desc->text;
-        u2 c;
-       size_t len=2;
-        while ((c=utf_nextu2(&utf_ptr))!=')') {
-                switch (c) {
-                        case 'I':
-                        case 'S':
-                        case 'B':
-                        case 'C':
-                        case 'Z':
-                        case 'J':
-                        case 'F':
-                        case 'D':
-                               len ++;
-                               break;
-                        case '[':
-                                len = len+2;
-                                break;
-                        case 'L':
-                                len++;
-                                while ( (c=utf_nextu2(&utf_ptr)) != ';')
-                                        len++;
-                                len=len+2;
-                                break;
-                        case '(':
-                                break;
-                        default: panic ("invalid method descriptor");
-                }
-        }
-       return len;
-
-}
-
-static void codegen_fillInOverloadPart(char *target,utf *desc) {
-        char *utf_ptr=desc->text;
-        u2 c;
-       char* insertpos=&target[strlen(target)];
-       *(insertpos++)='_';
-       *(insertpos++)='_';
-        while ((c=utf_nextu2(&utf_ptr))!=')') {
-                switch (c) {
-                        case 'I':
-                        case 'S':
-                        case 'B':
-                        case 'C':
-                        case 'Z':
-                        case 'J':
-                        case 'F':
-                        case 'D':
-                                *(insertpos++)=c;
-                                break;
-                        case '[':
-                               *(insertpos++)='_';
-                               *(insertpos++)='3';
-                                break;
-                        case 'L':
-                               *(insertpos++)='L';
-                                while ( (c=utf_nextu2(&utf_ptr)) != ';')
-                                       if ( ((c>='a') && (c<='z'))  ||
-                                               ((c>='A') && (c<='Z')) ||
-                                               ((c>='0') && (c<='9')) )
-                                                       *(insertpos++)=c;
-                                       else *(insertpos++)='_';
-                               *(insertpos++)='_';
-                               *(insertpos++)='2';
-                                break;
-                        case '(':
-                                break;
-                        default: panic ("invalid method descriptor");
-                }
-        }
-       *insertpos='\0';
-
-}
-
-static void codegen_resolve_native(methodinfo *m,void **insertionPoint,void *jmpTarget,void **jmpPatchTarget) {
-  char *nativeName, *nativeNameEscape;
-  size_t nativeLen;
-  size_t i;
-       void *lib;
-       void *sym;
-
-  builtin_monitorenter((java_objectheader*) m);
-#if defined(__X86_64__)
-  if ((*((s4*)jmpPatchTarget))==((s4)jmpTarget)) {
-#else
-  if ((*jmpPatchTarget)==jmpTarget) {
-#endif
-    builtin_monitorexit((java_objectheader*) m);
-    return;
-  }
-  /*log_text("trying to resolve a native method");
-  utf_display(m->class->name);
-  utf_display(m->name);*/
-  
-  lib=dlopen(0,RTLD_NOW | RTLD_GLOBAL); /* open the application execution image */
-  if (lib) { /* it did work -> good, otherwise fail with error*/
-    int ok=0;
-    /*generate the name of the native function in the form Java_package1_package2...._classname_methodname*/
-    nativeLen=/*Java_*/5+strlen(m->class->name->text)+/*_*/1+strlen(m->name->text)+/*\0*/1;
-    nativeName=MNEW(char,nativeLen);
-    sprintf(nativeName,"Java_%s/%s",m->class->name->text,m->name->text);
-       i=5;
-    while (i<nativeLen) {
-               if (nativeName[i]=='_') { /* escape underscore */
-                       nativeNameEscape = MNEW(char,nativeLen+1);
-                       memcpy(nativeNameEscape,nativeName,i+1);
-                       nativeNameEscape[i+1] = '1'; /* escape sequence for _ is _1 */
-                       memcpy(&nativeNameEscape[i+2],&nativeName[i+1],nativeLen-i-1);
-                       MFREE(nativeName,char,nativeLen);
-                       i++;
-                       nativeLen++;
-                       nativeNameEscape[nativeLen]=0;
-                       nativeName=nativeNameEscape;
-               }
-               if (nativeName[i]=='/') nativeName[i]='_';
-               i++;
-    } 
-
-/*     printf("nativename: %s\n",nativeName); */
-
-    /*try to find the symbal fo the function */
-    sym=dlsym(lib,nativeName);
-    if (sym) {
-      ok=1; /* it worked, everything fine */
-      /*log_text("resolved");*/
-      MFREE(nativeName,char,nativeLen);
-    } else { /* we didn't find the symbol yet, try to resolve an overlaoded function (having the types in it's name*/
-      size_t overloadedNativeLen=nativeLen+codegen_overloadPartLen(m->descriptor);
-      char *overloadedNative=MNEW(char,overloadedNativeLen);
-      sprintf(overloadedNative,"%s",nativeName);
-      MFREE(nativeName,char,nativeLen);
-      codegen_fillInOverloadPart(overloadedNative,m->descriptor);
-      /*log_text("symbol not found,trying harder (overloaded member ?)");*/
-      sym=dlsym(lib,overloadedNative);
-      if (sym) {
-        MFREE(overloadedNative,char,overloadedNativeLen);
-        ok=1; /* we eventually found the native function -> everything ok*/
-        /*log_text("resolved");*/
-      } else { 
-         /* we failed to find the native function within the execution image (app + loaded libraries) -> will cause an exit*/
-         MFREE(overloadedNative,char,overloadedNativeLen);
-         log_text("It was not possible to find the native function implementation. Not even in overloading case");
-      }
-   }
-    /* patch the address of the native function into the stub and make the stub jump over this function call in the future */
-    if (ok) {
-      (*insertionPoint)=sym;
-#if defined(__X86_64__)
-      (*((s4*)jmpPatchTarget))=(s4)jmpTarget;
-#else
-      (*jmpPatchTarget)=jmpTarget;
-#endif
-      builtin_monitorexit((java_objectheader *) m );
-      return;
-    }
-
-  } else log_text("library not found");
-  
-  /* There was an error, either the app image could not be opened or the native does not exist in the application and the
-     loaded libraries. Show an additional error and exit the vm*/
-  {
-    char *info;
-    size_t slen;
-    slen=2+strlen(m->class->name->text)+strlen(m->name->text)+strlen(m->descriptor->text);
-    info=(char*)MNEW(char,slen);
-    sprintf(info,"%s.%s%s",m->class->name->text,m->name->text,m->descriptor->text);
-    
-    builtin_monitorexit((java_objectheader *) m );
-    throw_cacao_exception_exit(string_java_lang_LinkageError,
-                                                       info);
-  }
-  
-}
-#endif
-
-
-#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