* Removed all Id tags.
[cacao.git] / src / vm / jit / intrp / codegen.c
index 0d3459a5cd2098743896513d9ca366b76258c4ad..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 5680 2006-10-04 22:39:44Z 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 *);
@@ -282,6 +280,8 @@ struct builtin_gen builtin_gen_table[] = {
 
 *******************************************************************************/
 
+#define I(value)   iptr[0].sx.val.i = (value); break;
+
 bool intrp_codegen(jitdata *jd)
 {
        methodinfo         *m;
@@ -290,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;
@@ -313,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  
@@ -353,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);
        }                       
@@ -411,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:
@@ -428,9 +441,29 @@ switch_again:
                                }
                        }
 
+                       /* optimize ICONST (2^x) .. IDIV --> IDIVPOW2 (const) */
+
+                       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)
+       case 0x00000100: I( 8) case 0x00000200: I( 9) case 0x00000400: I(10) case 0x00000800: I(11)
+       case 0x00001000: I(12) case 0x00002000: I(13) case 0x00004000: I(14) case 0x00008000: I(15)
+       case 0x00010000: I(16) case 0x00020000: I(17) case 0x00040000: I(18) case 0x00080000: I(19)
+       case 0x00100000: I(20) case 0x00200000: I(21) case 0x00400000: I(22) case 0x00800000: I(23)
+       case 0x01000000: I(24) case 0x02000000: I(25) case 0x04000000: I(26) case 0x08000000: I(27)
+       case 0x10000000: I(28) case 0x20000000: I(29) case 0x40000000: I(30) case 0x80000000: I(31)
+       default: goto dont_opt_IDIVPOW2;
+                               }
+                               iptr[0].opc = ICMD_IDIVPOW2;
+                               iptr[1].opc = ICMD_NOP;
+                               goto switch_again;
+                       }
+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;
@@ -454,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:
@@ -471,9 +504,29 @@ dont_opt_IFxx:
                                }
                        }
 
+                       /* optimize LCONST (2^x) .. LDIV --> LDIVPOW2 (const) */
+
+                       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)
+       case 0x00000100: I( 8) case 0x00000200: I( 9) case 0x00000400: I(10) case 0x00000800: I(11)
+       case 0x00001000: I(12) case 0x00002000: I(13) case 0x00004000: I(14) case 0x00008000: I(15)
+       case 0x00010000: I(16) case 0x00020000: I(17) case 0x00040000: I(18) case 0x00080000: I(19)
+       case 0x00100000: I(20) case 0x00200000: I(21) case 0x00400000: I(22) case 0x00800000: I(23)
+       case 0x01000000: I(24) case 0x02000000: I(25) case 0x04000000: I(26) case 0x08000000: I(27)
+       case 0x10000000: I(28) case 0x20000000: I(29) case 0x40000000: I(30) case 0x80000000: I(31)
+       default: goto dont_opt_LDIVPOW2;
+                               }
+                               iptr[0].opc = ICMD_LDIVPOW2;
+                               iptr[1].opc = ICMD_NOP;
+                               goto switch_again;
+                       }
+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;
@@ -720,14 +773,11 @@ dont_opt_IF_Lxx:
                        gen_LREM(cd);
                        break;
 
-                       /* the *POW2 instructions are not used currently */
-#if 0
                case ICMD_IDIVPOW2:   /* ..., value  ==> ..., value << constant       */
                                      /* val.i = constant                             */
                                      
                        gen_IDIVPOW2(cd, iptr->sx.val.i);
                        break;
-#endif
 
                case ICMD_IREMPOW2:   /* ..., value  ==> ..., value % constant        */
                                      /* val.i = constant                             */
@@ -735,13 +785,11 @@ dont_opt_IF_Lxx:
                        gen_IREMPOW2(cd, iptr->sx.val.i);
                        break;
 
-#if 0
                case ICMD_LDIVPOW2:   /* ..., value  ==> ..., value << constant       */
                                      /* val.i = constant                             */
                                      
                        gen_LDIVPOW2(cd, iptr->sx.val.i);
                        break;
-#endif
 
                case ICMD_LREMPOW2:   /* ..., value  ==> ..., value % constant        */
                                      /* val.l = constant                             */
@@ -814,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;
@@ -1061,6 +1109,7 @@ dont_opt_IF_LCMPxx:
                        }
                        else {
                                fi        = iptr->sx.s23.s3.fmiref->p.field;
+                               uf        = NULL;
                                fieldtype = fi->type;
                        }
 
@@ -1111,6 +1160,7 @@ dont_opt_IF_LCMPxx:
                        }
                        else {
                                fi        = iptr->sx.s23.s3.fmiref->p.field;
+                               uf        = NULL;
                                fieldtype = fi->type;
                        }
 
@@ -1162,6 +1212,7 @@ dont_opt_IF_LCMPxx:
                        }
                        else {
                                fi        = iptr->sx.s23.s3.fmiref->p.field;
+                               uf        = NULL;
                                fieldtype = fi->type;
                        }
 
@@ -1204,6 +1255,7 @@ dont_opt_IF_LCMPxx:
                        }
                        else {
                                fi        = iptr->sx.s23.s3.fmiref->p.field;
+                               uf        = NULL;
                                fieldtype = fi->type;
                        }
 
@@ -1478,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);
                        }
@@ -1486,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 ==> ...                      */
@@ -1497,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);
                        }
@@ -1505,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:       /* ...  ==> ...                               */
@@ -1515,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);
                        }
@@ -1523,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;
 
 
@@ -1557,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;
 
@@ -1589,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;
 
@@ -1725,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 */
                
@@ -1772,7 +1825,7 @@ dont_opt_IF_LCMPxx:
    +-------------+ <-- stub
    | codeptr     |
    +-------------+
-   | maxlocals   |
+   | framesize   |  (in ptrint units, does not include return address)
    +-------------+
    | TRANSLATE   |
    +-------------+
@@ -1785,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
@@ -1796,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);
 
@@ -1806,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 */
 
@@ -1824,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;
@@ -1933,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 */
@@ -2186,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 */