replace helper_* calls in the pathers with calls to resolve_*_eager
[cacao.git] / src / vm / jit / codegen.inc
index 352af7972d2a18c606e9bf1d7be0886d6771e6f8..b65d46647015a4f7ec3e2422688269f9c1fa1820 100644 (file)
@@ -1,4 +1,4 @@
-/* vm/jit/codegen.inc - architecture independent code generator
+/* src/vm/jit/codegen.inc - architecture independent code generator
 
    Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
    R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
    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 1953 2005-02-17 13:42:23Z christian $
+   $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);
@@ -380,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;
@@ -389,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
 }
 
@@ -431,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;
@@ -461,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;
@@ -470,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;
@@ -484,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;
@@ -512,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;
@@ -527,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)
 {
-#if defined(__I386__) || defined(__ALPHA__)
        linenumberref *lr;
 
        for (lr = cd->linenumberreferences; lr != NULL; lr = lr->next) {
@@ -563,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;
@@ -579,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 &&
@@ -594,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)
 {
@@ -631,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");
        }
@@ -643,6 +692,12 @@ void codegen_insertmethod(functionptr startpc, functionptr endpc)
 }
 
 
+/* codegen_findmethod **********************************************************
+
+   XXX
+
+*******************************************************************************/
+
 functionptr codegen_findmethod(functionptr pc)
 {
        methodtree_element *mtepc;
@@ -668,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)
@@ -680,55 +737,23 @@ functionptr codegen_findmethod(functionptr pc)
 
        return mte->startpc;
 }
-#endif
+#endif /* defined(__I386__) || defined(__X86_64__) || defined(__INTRP__) */
 
-#if defined(__ALPHA__)
-/*perhaps in the end I'll have to go for the tree version on alpha too, since this is insecure for eg segfault signals in native code,
-since it will still return an adress of a datasegment, but which will not be a valid one of a java method. This version is faster though (jowenn)*/
-void *codegen_findmethod(void *returnAdress)
- {
-        void *result;
-        s8 d;
-        void *dataseg;
-        d=*((s4*)returnAdress);
-        d=d<<48;
-        d=d>>48;
-        dataseg=returnAdress+d;
-        d=*(((s4*)returnAdress)+1);
-        d=d>>16;
-        d=d-0x177b;
-        if (d==0) {
-                d=*(((s4*)returnAdress)+1);
-                d=d<<16;
-                dataseg=dataseg+d;
-        }
-        return dataseg;
-#if 0
-        ldl     t0,0(ra)              /* load instruction LDA PV,xxx(RA)          */
-        sll     t0,48,t0
-        sra     t0,48,t0              /* isolate offset                           */
-        addq    t0,ra,pv              /* compute update address                   */
-        ldl     t0,4(ra)              /* load instruction LDAH PV,xxx(PV)         */
-        srl     t0,16,t0              /* isolate instruction code                 */
-        lda     t0,-0x177b(t0)        /* test for LDAH                            */
-        bne     t0,ex_stack_loop
-        ldl     t0,4(ra)              /* load instruction LDAH PV,xxx(RA)         */
-        sll     t0,16,t0              /* compute high offset                      */
-        addl    t0,0,t0               /* sign extend high offset                  */
-        addq    t0,pv,pv              /* compute update address                   */
-        br      ex_stack_loop
-#endif
-}
 
-#endif
+/* 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;
@@ -746,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);
+
+       /* copy data and code to their new location */
 
-       memcpy((void *) (long) m->mcode, cd->dsegtop - cd->dseglen, cd->dseglen);
-       memcpy((void *) ((long) m->mcode + cd->dseglen), cd->mcodebase, mcodelen);
+       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) ((long) m->mcode + cd->dseglen);
+       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;
        }
 
-#if defined(__I386__) || defined(__ALPHA__)
        /* 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;
                }
        }
@@ -808,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;
@@ -830,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
@@ -848,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)
 {
@@ -869,39 +1149,30 @@ static int reg_of_var(registerdata *rd, stackptr v, int tempregnum)
        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 < FLT_ARG_CNT) {
-                               v->regoff = rd->argfltregs[v->varnum];
-                               return(rd->argfltregs[v->varnum]);
-                       }
-
-#if defined(__POWERPC__)
-                       v->regoff += 6;
-#else
-                       v->regoff -= FLT_ARG_CNT;
-#endif
-
-               } else {
-#if defined(__POWERPC__)
-                       if (v->varnum < INT_ARG_CNT - (IS_2_WORD_TYPE(v->type) != 0)) {
-#else
-                       if (v->varnum < INT_ARG_CNT) {
+               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 -= INT_ARG_CNT;
+#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;
        }
@@ -938,201 +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;
-
-#if defined(USE_THREADS)
-  builtin_monitorenter((java_objectheader*) m);
-#endif
-
-#if defined(__X86_64__)
-  if ((*((s4*)jmpPatchTarget))==((s4)jmpTarget)) {
-#else
-  if ((*jmpPatchTarget)==jmpTarget) {
-#endif
-
-#if defined(USE_THREADS)
-    builtin_monitorexit((java_objectheader*) m);
-#endif
-
-    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
-
-#if defined(USE_THREADS)
-      builtin_monitorexit((java_objectheader *) m );
-#endif
-
-      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);
-    
-#if defined(USE_THREADS)
-    builtin_monitorexit((java_objectheader *) m );
-#endif
-
-    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