* src/vm/jit/parse.c (parse_resolve_exception_table): Do not use
[cacao.git] / src / vm / jit / parse.c
index 85859ca2277a0ad9743abc6f386726e623569b67..e604a943136eafe8babe812a0ee8b4f8c44ef6bc 100644 (file)
@@ -31,7 +31,7 @@
             Joseph Wenninger
             Christian Thalinger
 
-   $Id: parse.c 5718 2006-10-07 23:56:43Z edwin $
+   $Id: parse.c 5790 2006-10-16 09:59:52Z edwin $
 
 */
 
@@ -148,83 +148,177 @@ static instruction *parse_realloc_instructions(parsedata_t *pd, s4 ipc, s4 n)
 }
 
 
-/*******************************************************************************
+/* parse_mark_exception_boundaries *********************************************
 
-       function 'parse' scans the JavaVM code and generates intermediate code
+   Mark exception handlers and the boundaries of the handled regions as
+   basic block boundaries.
 
-       During parsing the block index table is used to store at bit pos 0
-       a flag which marks basic block starts and at position 1 to 31 the
-       intermediate instruction index. After parsing the block index table
-       is scanned, for marked positions a block is generated and the block
-       number is stored in the block index table.
+   IN:
+       jd...............current jitdata
+
+   RETURN VALUE:
+       >= 0.............the number of new basic blocks marked
+          -1...............an exception has been thrown
 
 *******************************************************************************/
 
-static exceptiontable * fillextable(
-                                                                       jitdata *jd,
-                                                                       methodinfo *m, 
-                                                                       exceptiontable *extable, 
-                                                                       exceptiontable *raw_extable, 
-                                                               int exceptiontablelength, 
-                                                                       int *block_count)
+static int parse_mark_exception_boundaries(jitdata *jd)
 {
-       int b_count, p, src;
+       s4                   b_count;
+       s4                   pc;
+       s4                   i;
+       s4                   len;
+       raw_exception_entry *rex;
+       methodinfo          *m;
+
+       m = jd->m;
        
-       if (exceptiontablelength == 0) 
-               return extable;
+       len = m->rawexceptiontablelength;
 
-       b_count = *block_count;
+       if (len == 0)
+               return 0;
+
+       b_count = 0;
+       rex = m->rawexceptiontable;
+
+       for (i = 0; i < len; ++i, ++rex) {
 
-       for (src = exceptiontablelength-1; src >=0; src--) {
                /* the start of the handled region becomes a basic block start */
-               p = raw_extable[src].startpc;
-               CHECK_BYTECODE_INDEX(p);
-               extable->startpc = p;
-               MARK_BASICBLOCK(p);
+
+               pc = rex->startpc;
+               CHECK_BYTECODE_INDEX(pc);
+               MARK_BASICBLOCK(pc);
                
-               p = raw_extable[src].endpc; /* see JVM Spec 4.7.3 */
-               CHECK_BYTECODE_INDEX_EXCLUSIVE(p);
+               pc = rex->endpc; /* see JVM Spec 4.7.3 */
+               CHECK_BYTECODE_INDEX_EXCLUSIVE(pc);
+
+               /* check that the range is valid */
 
 #if defined(ENABLE_VERIFIER)
-               if (p <= raw_extable[src].startpc) {
+               if (pc <= rex->startpc) {
                        exceptions_throw_verifyerror(m,
                                "Invalid exception handler range");
-                       return NULL;
+                       return -1;
                }
 #endif
-               extable->endpc = p;
                
                /* end of handled region becomes a basic block boundary  */
                /* (If it is the bytecode end, we'll use the special     */
                /* end block that is created anyway.)                    */
-               if (p < m->jcodelength) 
-                       MARK_BASICBLOCK(p);
+
+               if (pc < m->jcodelength)
+                       MARK_BASICBLOCK(pc);
 
                /* the start of the handler becomes a basic block start  */
-               p = raw_extable[src].handlerpc;
-               CHECK_BYTECODE_INDEX(p);
-               extable->handlerpc = p;
-               MARK_BASICBLOCK(p);
-
-               extable->catchtype = raw_extable[src].catchtype;
-               extable->next = NULL;
-               extable->down = &extable[1];
-               extable--;
+
+               pc = rex->handlerpc;
+               CHECK_BYTECODE_INDEX(pc);
+               MARK_BASICBLOCK(pc);
        }
 
-       *block_count = b_count;
-       
        /* everything ok */
-       return extable;
+
+       return b_count;
 
 #if defined(ENABLE_VERIFIER)
 throw_invalid_bytecode_index:
        exceptions_throw_verifyerror(m,
                                                                 "Illegal bytecode index in exception table");
-       return NULL;
+       return -1;
 #endif
 }
 
+
+/* parse_resolve_exception_table ***********************************************
+
+   Enter the exception handlers and their ranges, resolved to basicblock *s,
+   in the jitdata.
+
+   IN:
+       jd...............current jitdata
+
+   RETURN VALUE:
+          true.............everything ok
+          false............an exception has been thrown
+
+*******************************************************************************/
+
+static bool parse_resolve_exception_table(jitdata *jd)
+{
+       methodinfo          *m;
+       raw_exception_entry *rex;
+       exception_entry     *ex;
+       s4                   i;
+       s4                   len;
+       classinfo           *exclass;
+
+       m = jd->m;
+
+       len = m->rawexceptiontablelength;
+
+       /* common case: no handler entries */
+
+       if (len == 0)
+               return true;
+
+       /* allocate the exception table */
+
+       jd->exceptiontablelength = len;
+       jd->exceptiontable = DMNEW(exception_entry, len + 1); /* XXX why +1? */
+
+       /* copy and resolve the entries */
+
+       ex = jd->exceptiontable;
+       rex = m->rawexceptiontable;
+
+       for (i = 0; i < len; ++i, ++rex, ++ex) {
+               /* resolve instruction indices to basic blocks */
+
+               ex->start   = BLOCK_OF(rex->startpc);
+               ex->end     = BLOCK_OF(rex->endpc);
+               ex->handler = BLOCK_OF(rex->handlerpc);
+
+               /* lazily resolve the catchtype */
+
+               if (rex->catchtype.any != NULL) {
+                       if (!resolve_classref_or_classinfo(m,
+                                                                                          rex->catchtype,
+                                                                                          resolveLazy, true, false,
+                                                                                          &exclass))
+                               return false;
+
+                       /* if resolved, enter the result of resolution in the table */
+
+                       if (exclass != NULL)
+                               rex->catchtype.cls = exclass;
+               }
+
+               ex->catchtype = rex->catchtype;
+               ex->next = NULL;   /* set by loop analysis */
+               ex->down = ex + 1; /* link to next exception entry */
+       }
+
+       /* terminate the ->down linked list */
+
+       assert(ex != jd->exceptiontable);
+       ex[-1].down = NULL;
+
+       return true;
+}
+
+
+/*******************************************************************************
+
+       function 'parse' scans the JavaVM code and generates intermediate code
+
+       During parsing the block index table is used to store at bit pos 0
+       a flag which marks basic block starts and at position 1 to 31 the
+       intermediate instruction index. After parsing the block index table
+       is scanned, for marked positions a block is generated and the block
+       number is stored in the block index table.
+
+*******************************************************************************/
+
 /*** macro for checking the length of the bytecode ***/
 
 #if defined(ENABLE_VERIFIER)
@@ -241,7 +335,6 @@ bool parse(jitdata *jd)
 {
        methodinfo  *m;                     /* method being parsed                */
        codeinfo    *code;
-       codegendata *cd;
        parsedata_t  pd;
        instruction *iptr;                  /* current ptr into instruction array */
        s4           ipc;                   /* intermediate instruction counter   */
@@ -250,7 +343,7 @@ bool parse(jitdata *jd)
        s4           opcode;                /* java opcode                        */
        s4           i;
        s4           j;
-       int  b_count = 0;           /* basic block counter                      */
+       int  b_count;               /* basic block counter                      */
        int  s_count = 0;           /* stack element counter                    */
        bool blockend = false;      /* true if basic block end has been reached */
        bool iswide = false;        /* true if last instruction was a wide      */
@@ -274,11 +367,10 @@ bool parse(jitdata *jd)
 
        m    = jd->m;
        code = jd->code;
-       cd   = jd->cd;
 
        /* allocate buffers for local variable renaming */
-       local_map = DMNEW(int, cd->maxlocals * 5);
-       for (i = 0; i < cd->maxlocals; i++) {
+       local_map = DMNEW(int, m->maxlocals * 5);
+       for (i = 0; i < m->maxlocals; i++) {
                local_map[i * 5 + 0] = 0;
                local_map[i * 5 + 1] = 0;
                local_map[i * 5 + 2] = 0;
@@ -295,18 +387,15 @@ bool parse(jitdata *jd)
        iptr = pd.instructions;
        ipc  = 0;
   
-       /* compute branch targets of exception table */
+       /* mark basic block boundaries for exception table */
 
-       if (!fillextable(jd, m,
-                       &(cd->exceptiontable[cd->exceptiontablelength-1]),
-                       m->exceptiontable,
-                       m->exceptiontablelength,
-                       &b_count))
-       {
+       b_count = parse_mark_exception_boundaries(jd);
+       if (b_count < 0)
                return false;
-       }
 
-       s_count = 1 + m->exceptiontablelength; /* initialize stack element counter   */
+       /* initialize stack element counter */
+
+       s_count = 1 + m->rawexceptiontablelength;
 
 #if defined(ENABLE_THREADS)
        if (checksync && (m->flags & ACC_SYNCHRONIZED))
@@ -1030,12 +1119,12 @@ jsr_tail:
 #if defined(ENABLE_VERIFIER)
                                if (!JITDATA_HAS_FLAG_VERIFY(jd)) {
 #endif
-                                       result = resolve_field_lazy(jd, iptr, m);
+                                       result = resolve_field_lazy(m, fr);
                                        if (result == resolveFailed)
                                                return false;
 
                                        if (result != resolveSucceeded) {
-                                               uf = create_unresolved_field(m->class, m, iptr);
+                                               uf = resolve_create_unresolved_field(m->class, m, iptr);
 
                                                if (uf == NULL)
                                                        return false;
@@ -1103,12 +1192,28 @@ invoke_method:
 #if defined(ENABLE_VERIFIER)
                        if (!JITDATA_HAS_FLAG_VERIFY(jd)) {
 #endif
-                               result = resolve_method_lazy(jd, iptr, m);
+                               result = resolve_method_lazy(m, mr, 
+                                               (opcode == JAVA_INVOKESPECIAL));
                                if (result == resolveFailed)
                                        return false;
 
-                               if (result != resolveSucceeded) {
-                                       um = create_unresolved_method(m->class, m, iptr);
+                               if (result == resolveSucceeded) {
+                                       methodinfo *mi = iptr->sx.s23.s3.fmiref->p.method;
+
+                                       /* if this call is monomorphic, turn it into an INVOKESPECIAL */
+
+                                       assert(IS_FMIREF_RESOLVED(iptr->sx.s23.s3.fmiref));
+
+                                       if ((iptr->opc == ICMD_INVOKEVIRTUAL)
+                                               && (mi->flags & (ACC_FINAL | ACC_PRIVATE)))
+                                       {
+                                               iptr->opc = ICMD_INVOKESPECIAL;
+                                       }
+                               }
+                               else {
+                                       um = resolve_create_unresolved_method(m->class, m, mr,
+                                                       (opcode == JAVA_INVOKESTATIC),
+                                                       (opcode == JAVA_INVOKESPECIAL));
 
                                        if (!um)
                                                return false;
@@ -1468,7 +1573,6 @@ invoke_method:
        MZERO(bptr, basicblock, b_count + 1);
 
        b_count = 0;
-       jd->c_block_nr = 0;
 
        /* additional block if target 0 is not first intermediate instruction */
 
@@ -1478,8 +1582,8 @@ invoke_method:
                bptr->iinstr = jd->instructions;
                /* bptr->icount is set when the next block is allocated */
 
+               bptr->nr = b_count++;
                bptr++;
-               b_count++;
                bptr[-1].next = bptr;
        }
 
@@ -1510,8 +1614,8 @@ invoke_method:
 
                        jd->basicblockindex[p] = b_count;
 
+                       bptr->nr = b_count++;
                        bptr++;
-                       b_count++;
                        bptr[-1].next = bptr;
                }
        }
@@ -1525,37 +1629,15 @@ invoke_method:
        /* allocate additional block at end */
 
        BASICBLOCK_INIT(bptr,m);
+       bptr->nr = b_count;
+       jd->basicblockindex[m->jcodelength] = b_count;
 
        /* set basicblock pointers in exception table */
 
-       if (cd->exceptiontablelength > 0) {
-               cd->exceptiontable[cd->exceptiontablelength - 1].down = NULL;
-       }
-
-       for (i = 0; i < cd->exceptiontablelength; ++i) {
-               p = cd->exceptiontable[i].startpc;
-               cd->exceptiontable[i].start = jd->basicblocks + jd->basicblockindex[p];
-
-               p = cd->exceptiontable[i].endpc;
-               cd->exceptiontable[i].end = (p == m->jcodelength) ? (jd->basicblocks + jd->basicblockcount /*+ 1*/) : (jd->basicblocks + jd->basicblockindex[p]);
-
-               p = cd->exceptiontable[i].handlerpc;
-               cd->exceptiontable[i].handler = jd->basicblocks + jd->basicblockindex[p];
-       }
-
-       /* XXX activate this if you want to try inlining */
-#if 0
-       for (i = 0; i < m->exceptiontablelength; ++i) {
-               p = m->exceptiontable[i].startpc;
-               m->exceptiontable[i].start = jd->basicblocks + jd->basicblockindex[p];
-
-               p = m->exceptiontable[i].endpc;
-               m->exceptiontable[i].end = (p == m->jcodelength) ? (jd->basicblocks + jd->basicblockcount /*+ 1*/) : (jd->basicblocks + jd->basicblockindex[p]);
+       if (!parse_resolve_exception_table(jd))
+               return false;
 
-               p = m->exceptiontable[i].handlerpc;
-               m->exceptiontable[i].handler = jd->basicblocks + jd->basicblockindex[p];
-       }
-#endif
+       /* store the local map */
 
        jd->local_map = local_map;
 
@@ -1572,7 +1654,7 @@ invoke_method:
                /* iterate over local_map[0..m->maxlocals*5] and set all existing  */
                /* index,type pairs (local_map[index*5+type]==1) to an unique value */
                /* -> == new local var index */
-               for(i = 0; i < (cd->maxlocals * 5); i++, mapptr++) {
+               for(i = 0; i < (m->maxlocals * 5); i++, mapptr++) {
                        if (*mapptr)
                                *mapptr = nlocals++;
                        else
@@ -1592,6 +1674,11 @@ invoke_method:
 
                jd->vartop = nlocals;
 
+               /* reserve extra variables needed by stack analyse */
+
+               jd->varcount += STACK_EXTRA_VARS;
+               jd->vartop   += STACK_EXTRA_VARS;
+
                /* The verifier needs space for saving invars in some cases and */
                /* extra variables.                                             */
 
@@ -1608,7 +1695,7 @@ invoke_method:
 
                /* set types of all locals in jd->var */
 
-               for(mapptr = local_map, i = 0; i < (cd->maxlocals * 5); i++, mapptr++)
+               for(mapptr = local_map, i = 0; i < (m->maxlocals * 5); i++, mapptr++)
                        if (*mapptr != UNUSED)
                                VAR(*mapptr)->type = i%5;
        }