* Removed all Id tags.
[cacao.git] / src / vm / jit / intrp / codegen.c
index 56f5d03b3aea3540f33ff65225eb56f4645e0409..e49678bea92f6f5d4c51fb37c8c0a4068351a4c4 100644 (file)
@@ -1,6 +1,6 @@
 /* src/vm/jit/intrp/codegen.c - code generator for Interpreter
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   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
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Christian Thalinger
-            Anton Ertl
-                       
-   Changes: Edwin Steiner
-
-   $Id: codegen.c 5682 2006-10-04 23:05:15Z edwin $
-
 */
 
 
 #include "vm/jit/intrp/codegen.h"
 #include "vm/jit/intrp/intrp.h"
 
+#include "mm/memory.h"
+
 #include "native/native.h"
+
 #include "vm/builtin.h"
-#include "vm/class.h"
 #include "vm/exceptions.h"
 #include "vm/global.h"
-#include "vm/options.h"
 #include "vm/stringlocal.h"
 #include "vm/vm.h"
+
 #include "vm/jit/asmpart.h"
 #include "vm/jit/codegen-common.h"
 #include "vm/jit/dseg.h"
 #include "vm/jit/parse.h"
 #include "vm/jit/patcher.h"
 #include "vm/jit/stack.h"
+#include "vm/jit/stacktrace.h"
+
+#include "vmcore/class.h"
+#include "vmcore/options.h"
 
 
 #define gen_branch(_inst) { \
@@ -215,7 +212,8 @@ void genarg_avftbl(codegendata *cd1, vftbl_t *a)
 
 /* include the interpreter generation functions *******************************/
 
-#include "vm/jit/intrp/java-gen.i"
+/* Do not use "java-gen.i", it does not work with builddir. */
+#include <java-gen.i>
 
 
 typedef void (*genfunctionptr) (codegendata *);
@@ -292,7 +290,7 @@ bool intrp_codegen(jitdata *jd)
        s4                  i, len, s1, s2, d;
        basicblock         *bptr;
        instruction        *iptr;
-       exceptiontable     *ex;
+       exception_entry    *ex;
        u2                  currentline;
        methodinfo         *lm;             /* local methodinfo for ICMD_INVOKE*  */
        unresolved_method  *um;
@@ -315,33 +313,42 @@ bool intrp_codegen(jitdata *jd)
        lm = NULL;
        bte = NULL;
 
+       /* determine stackframe size (in units of ptrint slots) */
+
+       cd->stackframesize = m->maxlocals;
+
+#if defined(ENABLE_THREADS)
+       if (checksync && (m->flags & ACC_SYNCHRONIZED))
+               cd->stackframesize += 1;
+#endif
+
        /* create method header */
 
-       (void) dseg_addaddress(cd, jd->code);                  /* CodeinfoPointer */
-       (void) dseg_adds4(cd, m->maxlocals * SIZEOF_VOID_P);    /* FrameSize      */
+       (void) dseg_add_unique_address(cd, jd->code);
+       (void) dseg_add_unique_s4(cd, cd->stackframesize * SIZEOF_VOID_P);
 
 #if defined(ENABLE_THREADS)
        if (checksync && (m->flags & ACC_SYNCHRONIZED))
-               (void) dseg_adds4(cd, 1);                           /* IsSync         */
+               (void) dseg_add_unique_s4(cd, 1);
        else
 #endif
-               (void) dseg_adds4(cd, 0);                           /* IsSync         */
+               (void) dseg_add_unique_s4(cd, 0);
                                               
-       (void) dseg_adds4(cd, 0);                               /* IsLeaf         */
-       (void) dseg_adds4(cd, 0);                               /* IntSave        */
-       (void) dseg_adds4(cd, 0);                               /* FltSave        */
+       (void) dseg_add_unique_s4(cd, 0);
+       (void) dseg_add_unique_s4(cd, 0);
+       (void) dseg_add_unique_s4(cd, 0);
 
        dseg_addlinenumbertablesize(cd);
 
-       (void) dseg_adds4(cd, cd->exceptiontablelength);        /* ExTableSize    */
+       (void) dseg_add_unique_s4(cd, jd->exceptiontablelength);
 
        /* create exception table */
 
-       for (ex = cd->exceptiontable; ex != NULL; ex = ex->down) {
-               dseg_addtarget(cd, ex->start);
-               dseg_addtarget(cd, ex->end);
-               dseg_addtarget(cd, ex->handler);
-               (void) dseg_addaddress(cd, ex->catchtype.any);
+       for (ex = jd->exceptiontable; ex != NULL; ex = ex->down) {
+               dseg_add_target(cd, ex->start);
+               dseg_add_target(cd, ex->end);
+               dseg_add_target(cd, ex->handler);
+               (void) dseg_add_unique_address(cd, ex->catchtype.any);
        }
 
 #if 0  
@@ -355,10 +362,14 @@ bool intrp_codegen(jitdata *jd)
 
 #if defined(ENABLE_THREADS)
        if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
-               if (m->flags & ACC_STATIC)
+               if (m->flags & ACC_STATIC) {
                        gen_ACONST(cd, (java_objectheader *) m->class);
-               else
+               }
+               else {
                        gen_ALOAD(cd, 0);
+                       gen_DUP(cd);
+                       gen_ASTORE(cd, index2offset(m->maxlocals));
+               }
                
                gen_MONITORENTER(cd);
        }                       
@@ -413,7 +424,7 @@ switch_again:
 
                        /* optimize ICONST (2^x) .. IREM --> IREMPOW2 (const) */
 
-                       if (len >= 1 && iptr[1].opc == ICMD_IREM) {
+                       if (len >= 2 && iptr[1].opc == ICMD_IREM) {
                                switch (iptr[0].sx.val.i) {
        case 0x00000001: case 0x00000002: case 0x00000004: case 0x00000008:
        case 0x00000010: case 0x00000020: case 0x00000040: case 0x00000080:
@@ -432,7 +443,7 @@ switch_again:
 
                        /* optimize ICONST (2^x) .. IDIV --> IDIVPOW2 (const) */
 
-                       if (len >= 1 && iptr[1].opc == ICMD_IDIV) {
+                       if (len >= 2 && iptr[1].opc == ICMD_IDIV) {
                                switch (iptr[0].sx.val.i) {
                               case 0x00000002: I( 1) case 0x00000004: I( 2) case 0x00000008: I( 3)
        case 0x00000010: I( 4) case 0x00000020: I( 5) case 0x00000040: I( 6) case 0x00000080: I( 7)
@@ -452,7 +463,7 @@ dont_opt_IDIVPOW2:
 
                        /* optimize ICONST .. IF_ICMPxx --> IFxx (const) */
 
-                       if (len >= 1) {
+                       if (len >= 2) {
                                switch (iptr[1].opc) {
                                        case ICMD_IF_ICMPEQ: iptr[0].opc = ICMD_IFEQ; break;
                                        case ICMD_IF_ICMPNE: iptr[0].opc = ICMD_IFNE; break;
@@ -476,7 +487,7 @@ dont_opt_IFxx:
 
                        /* optimize LCONST (2^x) .. LREM --> LREMPOW2 (const) */
 
-                       if (len >= 1 && iptr[1].opc == ICMD_LREM) {
+                       if (len >= 2 && iptr[1].opc == ICMD_LREM) {
                                switch (iptr[0].sx.val.l) {
        case 0x00000001: case 0x00000002: case 0x00000004: case 0x00000008:
        case 0x00000010: case 0x00000020: case 0x00000040: case 0x00000080:
@@ -495,7 +506,7 @@ dont_opt_IFxx:
 
                        /* optimize LCONST (2^x) .. LDIV --> LDIVPOW2 (const) */
 
-                       if (len >= 1 && iptr[1].opc == ICMD_LDIV) {
+                       if (len >= 2 && iptr[1].opc == ICMD_LDIV) {
                                switch (iptr[0].sx.val.l) {
                               case 0x00000002: I( 1) case 0x00000004: I( 2) case 0x00000008: I( 3)
        case 0x00000010: I( 4) case 0x00000020: I( 5) case 0x00000040: I( 6) case 0x00000080: I( 7)
@@ -515,7 +526,7 @@ dont_opt_LDIVPOW2:
 
                        /* optimize LCONST .. LCMP .. IFxx (0) --> IF_Lxx */
 
-                       if (len >= 2 && iptr[1].opc == ICMD_LCMP && iptr[2].sx.val.i == 0) {
+                       if (len >= 3 && iptr[1].opc == ICMD_LCMP && iptr[2].sx.val.i == 0) {
                                switch (iptr[2].opc) {
                                        case ICMD_IFEQ: iptr[0].opc = ICMD_IF_LEQ; break;
                                        case ICMD_IFNE: iptr[0].opc = ICMD_IF_LNE; break;
@@ -851,7 +862,7 @@ dont_opt_IF_Lxx:
 
                        /* optimize LCMP .. IFxx (0) --> IF_LCMPxx */
 
-                       if (len >= 1 && iptr[1].sx.val.i == 0) {
+                       if (len >= 2 && iptr[1].sx.val.i == 0) {
                                switch (iptr[1].opc) {
                                        case ICMD_IFEQ: iptr[0].opc = ICMD_IF_LCMPEQ; break;
                                        case ICMD_IFNE: iptr[0].opc = ICMD_IF_LCMPNE; break;
@@ -1098,6 +1109,7 @@ dont_opt_IF_LCMPxx:
                        }
                        else {
                                fi        = iptr->sx.s23.s3.fmiref->p.field;
+                               uf        = NULL;
                                fieldtype = fi->type;
                        }
 
@@ -1148,6 +1160,7 @@ dont_opt_IF_LCMPxx:
                        }
                        else {
                                fi        = iptr->sx.s23.s3.fmiref->p.field;
+                               uf        = NULL;
                                fieldtype = fi->type;
                        }
 
@@ -1199,6 +1212,7 @@ dont_opt_IF_LCMPxx:
                        }
                        else {
                                fi        = iptr->sx.s23.s3.fmiref->p.field;
+                               uf        = NULL;
                                fieldtype = fi->type;
                        }
 
@@ -1241,6 +1255,7 @@ dont_opt_IF_LCMPxx:
                        }
                        else {
                                fi        = iptr->sx.s23.s3.fmiref->p.field;
+                               uf        = NULL;
                                fieldtype = fi->type;
                        }
 
@@ -1515,7 +1530,7 @@ dont_opt_IF_LCMPxx:
                                if (m->flags & ACC_STATIC) {
                                        gen_ACONST(cd, (java_objectheader *) m->class);
                                } else {
-                                       gen_ALOAD(cd, 0);
+                                       gen_ALOAD(cd, index2offset(m->maxlocals));
                                }
                                gen_MONITOREXIT(cd);
                        }
@@ -1523,7 +1538,7 @@ dont_opt_IF_LCMPxx:
                        if (opt_verbosecall)
                                gen_TRACERETURN(cd, m);
 
-                       gen_IRETURN(cd, index2offset(cd->maxlocals));
+                       gen_IRETURN(cd, index2offset(cd->stackframesize));
                        break;
 
                case ICMD_LRETURN:      /* ..., retvalue ==> ...                      */
@@ -1534,7 +1549,7 @@ dont_opt_IF_LCMPxx:
                                if (m->flags & ACC_STATIC) {
                                        gen_ACONST(cd, (java_objectheader *) m->class);
                                } else {
-                                       gen_ALOAD(cd, 0);
+                                       gen_ALOAD(cd, index2offset(m->maxlocals));
                                }
                                gen_MONITOREXIT(cd);
                        }
@@ -1542,7 +1557,7 @@ dont_opt_IF_LCMPxx:
                        if (opt_verbosecall)
                                gen_TRACELRETURN(cd, m);
 
-                       gen_LRETURN(cd, index2offset(cd->maxlocals));
+                       gen_LRETURN(cd, index2offset(cd->stackframesize));
                        break;
 
                case ICMD_RETURN:       /* ...  ==> ...                               */
@@ -1552,7 +1567,7 @@ dont_opt_IF_LCMPxx:
                                if (m->flags & ACC_STATIC) {
                                        gen_ACONST(cd, (java_objectheader *) m->class);
                                } else {
-                                       gen_ALOAD(cd, 0);
+                                       gen_ALOAD(cd, index2offset(m->maxlocals));
                                }
                                gen_MONITOREXIT(cd);
                        }
@@ -1560,7 +1575,7 @@ dont_opt_IF_LCMPxx:
                        if (opt_verbosecall)
                                gen_TRACERETURN(cd, m);
 
-                       gen_RETURN(cd, index2offset(cd->maxlocals));
+                       gen_RETURN(cd, index2offset(cd->stackframesize));
                        break;
 
 
@@ -1594,12 +1609,12 @@ dont_opt_IF_LCMPxx:
                        table += i;
 
                        while (--i >= 0) {
-                               dseg_addtarget(cd, BLOCK_OF(table->insindex)); 
+                               dseg_add_target(cd, BLOCK_OF(table->insindex)); 
                                --table;
                        }
                        }
 
-                       /* length of dataseg after last dseg_addtarget is used by load */
+                       /* length of dataseg after last dseg_add_target is used by load */
                        ((ptrint *)(cd->mcodeptr))[-2] = (ptrint) -(cd->dseglen);
                        break;
 
@@ -1626,15 +1641,15 @@ dont_opt_IF_LCMPxx:
                        /* build jump table top down and use address of lowest entry */
 
                        while (--i >= 0) {
-                               dseg_addtarget(cd, BLOCK_OF(lookup->target.insindex)); 
-                               dseg_addaddress(cd, lookup->value);
+                               dseg_add_target(cd, BLOCK_OF(lookup->target.insindex)); 
+                               dseg_add_unique_address(cd, lookup->value);
                                lookup++;
                        }
 
                        codegen_addreference(cd, BLOCK_OF(iptr->sx.s23.s3.lookupdefault.insindex));
                        }
 
-                       /* length of dataseg after last dseg_addtarget is used by load */
+                       /* length of dataseg after last dseg_add_target is used by load */
                        ((ptrint *)(cd->mcodeptr))[-2] = (ptrint) -(cd->dseglen);
                        break;
 
@@ -1762,7 +1777,8 @@ dont_opt_IF_LCMPxx:
                        break;
 
                default:
-                       *exceptionptr = new_internalerror("Unknown ICMD %d", iptr->opc);
+                       exceptions_throw_internalerror("Unknown ICMD %d during code generation",
+                                                                                  iptr->opc);
                        return false;
        } /* switch */
                
@@ -1809,7 +1825,7 @@ dont_opt_IF_LCMPxx:
    +-------------+ <-- stub
    | codeptr     |
    +-------------+
-   | maxlocals   |
+   | framesize   |  (in ptrint units, does not include return address)
    +-------------+
    | TRANSLATE   |
    +-------------+
@@ -1822,7 +1838,7 @@ dont_opt_IF_LCMPxx:
 
 *******************************************************************************/
 
-#define COMPILERSTUB_DATASIZE    1
+#define COMPILERSTUB_DATASIZE    2
 #define COMPILERSTUB_CODESIZE    4
 
 #define COMPILERSTUB_SIZE        COMPILERSTUB_DATASIZE + COMPILERSTUB_CODESIZE
@@ -1833,8 +1849,8 @@ u1 *intrp_createcompilerstub(methodinfo *m)
        Inst        *s;
        Inst        *d;
        codegendata *cd;
-       codeinfo    *code;
        s4           dumpsize;
+       s4           stackframesize;
 
        s = CNEW(Inst, COMPILERSTUB_SIZE);
 
@@ -1843,11 +1859,11 @@ u1 *intrp_createcompilerstub(methodinfo *m)
        d = s;
        s = s + COMPILERSTUB_DATASIZE;
 
-       /* Store the codeinfo pointer in the same place as in the
-          methodheader for compiled methods. */
+       /* The codeinfo pointer is actually a pointer to the
+          methodinfo. This fakes a codeinfo structure. */
 
-       code = code_codeinfo_new(m);
-       d[0] = (Inst *) code;
+       d[0] = (Inst *) m;
+       d[1] = (Inst *) &d[0];                                    /* fake code->m */
 
        /* mark start of dump memory area */
 
@@ -1861,11 +1877,19 @@ u1 *intrp_createcompilerstub(methodinfo *m)
        genarg_ainst(cd, s + 2);
 
        if (m->flags & ACC_NATIVE) {
-               genarg_i(cd, m->parseddesc->paramslots);
-       } else {
-               genarg_i(cd, m->maxlocals);
+               stackframesize = m->parseddesc->paramslots;
+       } 
+       else {
+               stackframesize = m->maxlocals;
+
+#if defined(ENABLE_THREADS)
+               if (checksync && (m->flags & ACC_SYNCHRONIZED))
+                       stackframesize += 1;
+#endif
        }
 
+       genarg_i(cd, stackframesize);
+
        gen_BBSTART;
        gen_TRANSLATE(cd, m);
        gen_BBEND;
@@ -1970,28 +1994,29 @@ u1 *intrp_createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
 #else
        u1      *cif;
 #endif
+       s4            stackframesize;
 
        /* get required compiler data */
 
-       m  = jd->m;
-       cd = jd->cd;
-       rd = jd->rd;
+       m    = jd->m;
+       code = jd->code;
+       cd   = jd->cd;
+       rd   = jd->rd;
 
-       /* create method header */
+       /* determine stackframe size (in units of ptrint) */
 
-       /* Store the codeinfo pointer in the same place as in the
-          methodheader for compiled methods. */
+       stackframesize = nmd->paramslots;
 
-       code = code_codeinfo_new(m);
+       /* create method header */
 
-       (void) dseg_addaddress(cd, code);                      /* CodeinfoPointer */
-       (void) dseg_adds4(cd, nmd->paramslots * SIZEOF_VOID_P); /* FrameSize      */
-       (void) dseg_adds4(cd, 0);                               /* IsSync         */
-       (void) dseg_adds4(cd, 0);                               /* IsLeaf         */
-       (void) dseg_adds4(cd, 0);                               /* IntSave        */
-       (void) dseg_adds4(cd, 0);                               /* FltSave        */
+       (void) dseg_add_unique_address(cd, code);              /* CodeinfoPointer */
+       (void) dseg_add_unique_s4(cd, stackframesize * SIZEOF_VOID_P); /*FrameSize*/
+       (void) dseg_add_unique_s4(cd, 0);                       /* IsSync         */
+       (void) dseg_add_unique_s4(cd, 0);                       /* IsLeaf         */
+       (void) dseg_add_unique_s4(cd, 0);                       /* IntSave        */
+       (void) dseg_add_unique_s4(cd, 0);                       /* FltSave        */
        dseg_addlinenumbertablesize(cd);
-       (void) dseg_adds4(cd, 0);                               /* ExTableSize    */
+       (void) dseg_add_unique_s4(cd, 0);                       /* ExTableSize    */
 
 #if defined(WITH_FFI)
        /* prepare ffi cif structure */
@@ -2223,14 +2248,14 @@ u1 *createcalljavafunction(methodinfo *m)
 
        /* create method header */
 
-       (void) dseg_addaddress(cd, NULL);                      /* CodeinfoPointer */
-       (void) dseg_adds4(cd, md->paramslots * SIZEOF_VOID_P);  /* FrameSize      */
-       (void) dseg_adds4(cd, 0);                               /* IsSync         */
-       (void) dseg_adds4(cd, 0);                               /* IsLeaf         */
-       (void) dseg_adds4(cd, 0);                               /* IntSave        */
-       (void) dseg_adds4(cd, 0);                               /* FltSave        */
+       (void) dseg_add_unique_address(cd, NULL);              /* CodeinfoPointer */
+       (void) dseg_add_unique_s4(cd, md->paramslots * SIZEOF_VOID_P);/* FrameSize*/
+       (void) dseg_add_unique_s4(cd, 0);                       /* IsSync         */
+       (void) dseg_add_unique_s4(cd, 0);                       /* IsLeaf         */
+       (void) dseg_add_unique_s4(cd, 0);                       /* IntSave        */
+       (void) dseg_add_unique_s4(cd, 0);                       /* FltSave        */
        dseg_addlinenumbertablesize(cd);
-       (void) dseg_adds4(cd, 0);                               /* ExTableSize    */
+       (void) dseg_add_unique_s4(cd, 0);                       /* ExTableSize    */
 
 
        /* generate code */