* src/vm/jit/stack.h (COPY): Prevent setting varkind to STACKVAR for stackslots copie...
authorchristian <none@none>
Thu, 16 Feb 2006 19:39:36 +0000 (19:39 +0000)
committerchristian <none@none>
Thu, 16 Feb 2006 19:39:36 +0000 (19:39 +0000)
(DUP) Likewise.
* src/vm/jit/stack.c (analyse_stack): Copy elimination and needed conflict resolution was implemented as
described in the CACAO paper. As "potential exception throwing instruction" for now only INVOKE*s are
regarded. Conflict resolution over DUPx and SWAP should be refined to be less conservative.
* src/vm/jit/jit.c (jit_init): Stackreq for JAVA_IINC is set to 0 again, since no dummy stackslot is
needed anymore for conflict resolution with XSTORE.
* src/vm/jit/allocator/simplereg.c (interface_regalloc): Reuse unused float and int argument registers
for interfaces, too.
(reg_free_temp): Regard the new stackslot flag STCOPY, before freeing a register/memory location.
(reg_alloc_dup): New function to allocate, if possible, the same register/memory location for stackslot
copied by DUPx and SWAP.
(allocate_scratch_registers): The new function reg_alloc_dup is used now for allocation at ICMD_DUPx and
ICMD_SWAP, if possible.
* src/vm/jit/jit.h:  Added STCOPY as stackslot flag to mark simultanously live stackslots with same
register after DUPx and SWAP.
* doc/stack.txt: Updated invariants to show the change with IINC (no dummy stacklot anymore).

doc/stack.txt
src/vm/jit/allocator/simplereg.c
src/vm/jit/jit.c
src/vm/jit/jit.h
src/vm/jit/stack.c
src/vm/jit/stack.h

index e973ad39b324efb22a2222c09d4a2b703c2694ac..603b87556e8a7a40b3c6590cd11cc87e7b5a5756 100644 (file)
@@ -42,6 +42,12 @@ The following invariants hold at all time for the stack representation:
     6) References can only go to lower memory addresses. That is, for each stack slot sp:
 
             (sp->prev == NULL) or (sp->prev < sp)
+    7) If an instruction produces any stackslots, iptr->dst points to the highest-address 
+       stackslot produced
+       Corollary: if iptr->dst points to curstack or below, the instruction does
+                   not produce any stackslots
+
 
     ATTENTION: The instack of a block and the slots produced within the block
                are *not* guaranteed to be adjacent (see figure below)!
index cf71e970762827125b347069cd3607ec9eae710c..9dd50db5dad1305504d5e5c78dd0ad04d86bc38c 100644 (file)
@@ -32,7 +32,7 @@
             Michael Starzinger
                        Edwin Steiner
 
-   $Id: simplereg.c 4454 2006-02-06 00:02:50Z edwin $
+   $Id: simplereg.c 4524 2006-02-16 19:39:36Z christian $
 
 */
 
@@ -70,6 +70,13 @@ static void allocate_scratch_registers(methodinfo *m, registerdata *rd);
        
 void regalloc(methodinfo *m, codegendata *cd, registerdata *rd)
 {
+       /* There is a problem with the use of unused float argument registers in */
+       /* leafmethods for stackslots on c7 (3* Dual Core AMD Opteron(tm)        */
+       /* Processor 270) - runtime for the jvm98 _mtrt benchmark is heaviliy    */
+       /* increased. This could be prevented by setting rd->argfltreguse to     */
+       /* FLT_ARG_CNT before calling allocate_scratch_registers and setting it  */
+       /* back to the original value before calling local_regalloc.             */
+
        interface_regalloc(m, cd, rd);
        allocate_scratch_registers(m, rd);
        local_regalloc(m, cd, rd);
@@ -159,8 +166,7 @@ static void interface_regalloc(methodinfo *m, codegendata *cd, registerdata *rd)
                                                                v->flags |= rd->interfaces[s][fltalloc].flags
                                                                        & INMEMORY;
                                                                v->regoff = rd->interfaces[s][fltalloc].regoff;
-                                                       } else if (!m->isleafmethod 
-                                                                          && (rd->argfltreguse < FLT_ARG_CNT)) {
+                                                       } else if (rd->argfltreguse < FLT_ARG_CNT) {
                                                                v->regoff = rd->argfltregs[rd->argfltreguse++];
                                                        } else if (rd->tmpfltreguse > 0) {
                                                                v->regoff = rd->tmpfltregs[--rd->tmpfltreguse];
@@ -208,9 +214,8 @@ static void interface_regalloc(methodinfo *m, codegendata *cd, registerdata *rd)
                                                                                v->regoff = 
                                                                                    rd->interfaces[s][intalloc].regoff;
                                                                } else 
-                                                                       if (!m->isleafmethod && 
-                                                                               (rd->argintreguse 
-                                                                                + intregsneeded < INT_ARG_CNT)) {
+                                                                       if (rd->argintreguse + intregsneeded 
+                                                                               < INT_ARG_CNT) {
 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
                                                                                if (intregsneeded) 
                                                                                        v->regoff=PACK_REGS( 
@@ -932,7 +937,10 @@ static void reg_new_temp_func(registerdata *rd, stackptr s)
 }
 
 
-#define reg_free_temp(rd,s) if (s->varkind == TEMPVAR) reg_free_temp_func(rd, s)
+#define reg_free_temp(rd,s) if ((s->varkind == TEMPVAR) && (!(s->flags & STCOPY))) reg_free_temp_func(rd, s)
+
+/* Do not free regs/memory locations used by Stackslots flagged STCOPY! There is still another Stackslot */
+/* alive using this reg/memory location */
 
 static void reg_free_temp_func(registerdata *rd, stackptr s)
 {
@@ -1021,7 +1029,30 @@ static void reg_free_temp_func(registerdata *rd, stackptr s)
        }
 }
 
-
+static bool reg_alloc_dup(stackptr src, stackptr dst) {
+       /* only copy TEMPVARS, do not mess with STACKVAR,      */
+       /* LOCALVAR, or ARGVAR        */
+       if ((src->varkind == TEMPVAR) && (dst->varkind == TEMPVAR)) {
+               /* can not allocate a REG_TMP to a REG_SAV Slot */
+               if (src->flags & INMEMORY) {
+                       dst->regoff  = src->regoff;
+                       dst->flags |= INMEMORY;
+                       return true;
+               } else if ((src->flags & SAVEDVAR) == (dst->flags & SAVEDVAR)) {
+                       dst->regoff  = src->regoff;
+                       dst->flags |= src->flags & SAVEDTMP;
+                       dst->flags |= src->flags & TMPARG;
+                       return true;
+               } else if ((dst->flags & SAVEDVAR) == 0) {
+                       /* can only use a REG_SAV as REG_TMP! */
+                       dst->regoff = src->regoff;
+                       dst->flags |= SAVEDTMP;
+                       return true;
+               } 
+       }
+       /* no copy possible - allocate a new reg/memory location*/
+       return false;
+}
 
 static void allocate_scratch_registers(methodinfo *m, registerdata *rd)
 {
@@ -1212,73 +1243,210 @@ static void allocate_scratch_registers(methodinfo *m, registerdata *rd)
                                        /* pop 0 push 1 dup */
                                        
                                case ICMD_DUP:
-                                       reg_new_temp(rd, dst);
+                                       /* src === dst->prev (identical Stackslot Element)     */
+                                       /* src --> dst       (copied value, take same reg/mem) */
+
+                                       if (!reg_alloc_dup(src, dst)) {
+                                               reg_new_temp(rd, dst);
+                                       } else {
+                                               dst->flags |= STCOPY;
+                                       }
                                        break;
 
                                        /* pop 0 push 2 dup */
                                        
                                case ICMD_DUP2:
-                                       reg_new_temp(rd, dst->prev);
-                                       reg_new_temp(rd, dst);
+                                       /* src->prev === dst->prev->prev->prev (identical Stackslot Element)     */
+                                       /* src       === dst->prev->prev       (identical Stackslot Element)     */
+                                       /* src->prev --> dst->prev             (copied value, take same reg/mem) */
+                                       /* src       --> dst                   (copied value, take same reg/mem) */
+                                                                                               
+                                       if (!reg_alloc_dup(src->prev, dst->prev)) {
+                                               reg_new_temp(rd, dst->prev);
+                                       } else {
+                                               dst->prev->flags |= STCOPY;
+                                       }
+                                       if (!reg_alloc_dup(src, dst)) {
+                                               reg_new_temp(rd, dst);
+                                       } else {
+                                               dst->flags |= STCOPY;
+                                       }
                                        break;
 
                                        /* pop 2 push 3 dup */
                                        
                                case ICMD_DUP_X1:
-                                       reg_free_temp(rd, src);
-                                       reg_new_temp(rd, dst);
-                                       reg_free_temp(rd, src->prev);
-                                       reg_new_temp(rd, dst->prev);
-                                       reg_new_temp(rd, dst->prev->prev);
+                                       /* src->prev --> dst->prev       (copied value, take same reg/mem) */
+                                       /* src       --> dst             (copied value, take same reg/mem) */
+                                       /* src       --> dst->prev->prev (copied value, take same reg/mem) */
+                                                                                               
+                                       {
+                                               bool ret, ret1;
+                                               if (!(ret = reg_alloc_dup(src, dst->prev->prev))) {
+                                                               reg_new_temp(rd, dst->prev->prev);
+                                               }
+                                               if (!(ret1 = reg_alloc_dup(src, dst))) {
+                                                               reg_new_temp(rd, dst);
+                                               }
+                                               if (!(ret || ret1)) {
+                                                       /* no reallocation was possible -> free src */
+                                                       reg_free_temp(rd, src);
+                                               }
+                                               if (ret && ret1) {
+                                                       dst->flags |= STCOPY;
+                                               }
+                                               if (!reg_alloc_dup(src->prev, dst->prev)) {
+                                                       reg_free_temp(rd, src->prev);
+                                                       reg_new_temp(rd, dst->prev);
+                                               }
+                                       }
                                        break;
 
                                        /* pop 3 push 4 dup */
                                        
                                case ICMD_DUP_X2:
-                                       reg_free_temp(rd, src);
-                                       reg_new_temp(rd, dst);
-                                       reg_free_temp(rd, src->prev);
-                                       reg_new_temp(rd, dst->prev);
-                                       reg_free_temp(rd, src->prev->prev);
-                                       reg_new_temp(rd, dst->prev->prev);
-                                       reg_new_temp(rd, dst->prev->prev->prev);
+                                       /* src->prev->prev --> dst->prev->prev        */
+                                       /* src->prev       --> dst->prev              */
+                                       /* src             --> dst                    */
+                                       /* src             --> dst->prev->prev->prev  */
+                                       
+                                       {
+                                               bool ret, ret1;
+                                               if (!(ret = reg_alloc_dup(src, dst->prev->prev->prev))) {
+                                                               reg_new_temp(rd, dst->prev->prev->prev);
+                                               }
+                                               if (!(ret1 = reg_alloc_dup(src, dst))) {
+                                                               reg_new_temp(rd, dst);
+                                               }
+                                               if (!(ret || ret1)) {
+                                                       /* no reallocation was possible -> free src */
+                                                       reg_free_temp(rd, src);
+                                               }
+                                               if (ret && ret1) {
+                                                       dst->flags |= STCOPY;
+                                               }
+                                               if (!reg_alloc_dup(src->prev, dst->prev)) {
+                                                       reg_free_temp(rd, src->prev);
+                                                       reg_new_temp(rd, dst->prev);
+                                               }
+                                               if (!reg_alloc_dup(src->prev->prev, dst->prev->prev)) {
+                                                       reg_free_temp(rd, src->prev->prev);
+                                                       reg_new_temp(rd, dst->prev->prev);
+                                               }
+                                       }
                                        break;
 
                                        /* pop 3 push 5 dup */
                                        
                                case ICMD_DUP2_X1:
-                                       reg_free_temp(rd, src);
-                                       reg_new_temp(rd, dst);
-                                       reg_free_temp(rd, src->prev);
-                                       reg_new_temp(rd, dst->prev);
-                                       reg_free_temp(rd, src->prev->prev);
-                                       reg_new_temp(rd, dst->prev->prev);
-                                       reg_new_temp(rd, dst->prev->prev->prev);
-                                       reg_new_temp(rd, dst->prev->prev->prev->prev);
+                                       /* src->prev->prev --> dst->prev->prev             */
+                                       /* src->prev       --> dst->prev                   */
+                                       /* src             --> dst                         */
+                                       /* src->prev       --> dst->prev->prev->prev->prev */
+                                       /* src             --> dst->prev->prev->prev       */
+                                                                                               
+                                       {
+                                               bool ret, ret1;
+                                               if (!(ret = reg_alloc_dup(src, dst->prev->prev->prev))) {
+                                                               reg_new_temp(rd, dst->prev->prev->prev);
+                                               }
+                                               if (!(ret1 = reg_alloc_dup(src, dst))) {
+                                                               reg_new_temp(rd, dst);
+                                               }
+                                               if (!(ret || ret1)) {
+                                                       /* no reallocation was possible -> free src */
+                                                       reg_free_temp(rd, src);
+                                               }
+                                               if (ret && ret1) {
+                                                       dst->flags |= STCOPY;
+                                               }
+
+                                               if (!(ret = reg_alloc_dup(src->prev, dst->prev->prev->prev->prev))) {
+                                                               reg_new_temp(rd, dst->prev->prev->prev->prev);
+                                               }
+                                               if (!(ret1 = reg_alloc_dup(src->prev, dst->prev))) {
+                                                               reg_new_temp(rd, dst->prev);
+                                               }
+                                               if (!(ret || ret1)) {
+                                                       /* no reallocation was possible -> free src->prev */
+                                                       reg_free_temp(rd, src->prev);
+                                               }
+                                               if (ret && ret1) {
+                                                       dst->prev->flags |= STCOPY;
+                                               }
+
+                                               if (!reg_alloc_dup(src->prev->prev, dst->prev->prev)) {
+                                                       reg_free_temp(rd, src->prev->prev);
+                                                       reg_new_temp(rd, dst->prev->prev);
+                                               }
+                                       }
                                        break;
 
                                        /* pop 4 push 6 dup */
                                        
                                case ICMD_DUP2_X2:
-                                       reg_free_temp(rd, src);
-                                       reg_new_temp(rd, dst);
-                                       reg_free_temp(rd, src->prev);
-                                       reg_new_temp(rd, dst->prev);
-                                       reg_free_temp(rd, src->prev->prev);
-                                       reg_new_temp(rd, dst->prev->prev);
-                                       reg_free_temp(rd, src->prev->prev->prev);
-                                       reg_new_temp(rd, dst->prev->prev->prev);
-                                       reg_new_temp(rd, dst->prev->prev->prev->prev);
-                                       reg_new_temp(rd, dst->prev->prev->prev->prev->prev);
+                                       /* src->prev->prev->prev --> dst->prev->prev->prev             */
+                                       /* src->prev->prev       --> dst->prev->prev                   */
+                                       /* src->prev             --> dst->prev                         */
+                                       /* src                   --> dst                               */
+                                       /* src->prev             --> dst->prev->prev->prev->prev->prev */
+                                       /* src                   --> dst->prev->prev->prev->prev       */
+                                                                                               
+                                       {
+                                               bool ret, ret1;
+                                               if (!(ret = reg_alloc_dup(src, dst->prev->prev->prev->prev))) {
+                                                               reg_new_temp(rd, dst->prev->prev->prev->prev);
+                                               }
+                                               if (!(ret1 = reg_alloc_dup(src, dst))) {
+                                                               reg_new_temp(rd, dst);
+                                               }
+                                               if (!(ret || ret1)) {
+                                                       /* no reallocation was possible -> free src */
+                                                       reg_free_temp(rd, src);
+                                               }
+                                               if (ret && ret1) {
+                                                       dst->flags |= STCOPY;
+                                               }
+
+                                               if (!(ret = reg_alloc_dup(src->prev, dst->prev->prev->prev->prev->prev))) {
+                                                               reg_new_temp(rd, dst->prev->prev->prev->prev->prev);
+                                               }
+                                               if (!(ret1 = reg_alloc_dup(src->prev, dst->prev))) {
+                                                               reg_new_temp(rd, dst->prev);
+                                               }
+                                               if (!(ret || ret1)) {
+                                                       /* no reallocation was possible -> free src->prev */
+                                                       reg_free_temp(rd, src->prev);
+                                               }
+                                               if (ret && ret1) {
+                                                       dst->prev->flags |= STCOPY;
+                                               }
+
+                                               if (!reg_alloc_dup(src->prev->prev, dst->prev->prev)) {
+                                                       reg_free_temp(rd, src->prev->prev);
+                                                       reg_new_temp(rd, dst->prev->prev);
+                                               }
+                                               if (!reg_alloc_dup(src->prev->prev->prev, dst->prev->prev->prev)) {
+                                                       reg_free_temp(rd, src->prev->prev->prev);
+                                                       reg_new_temp(rd, dst->prev->prev->prev);
+                                               }
+                                       }
                                        break;
 
                                        /* pop 2 push 2 swap */
                                        
                                case ICMD_SWAP:
-                                       reg_free_temp(rd, src);
-                                       reg_new_temp(rd, dst->prev);
-                                       reg_free_temp(rd, src->prev);
-                                       reg_new_temp(rd, dst);
+                                       /* src       --> dst->prev   (copy) */
+                                       /* src->prev --> dst         (copy) */
+                                                                                               
+                                       if (!reg_alloc_dup(src, dst->prev)) {
+                                               reg_free_temp(rd, src);
+                                               reg_new_temp(rd, dst->prev);
+                                       }
+                                       if (!reg_alloc_dup(src->prev, dst->prev)) {
+                                               reg_free_temp(rd, src->prev);
+                                               reg_new_temp(rd, dst);
+                                       }
                                        break;
 
                                        /* pop 2 push 1 */
index 31758e47b7183cb60d254d341172f3007694615d..df5d2e40e9e47f1e2191bf7cee676c946791f5d7 100644 (file)
@@ -31,7 +31,7 @@
             Christian Thalinger
             Christian Ullrich
 
-   $Id: jit.c 4478 2006-02-07 17:22:13Z edwin $
+   $Id: jit.c 4524 2006-02-16 19:39:36Z christian $
 
 */
 
@@ -1270,11 +1270,7 @@ void jit_init(void)
        stackreq[JAVA_IFNONNULL]    = 0;
        stackreq[JAVA_GOTO_W]       = 0;
        stackreq[JAVA_BREAKPOINT]   = 0;
-
-       /* we need one dummy stack slot for IINC in order to */
-       /* avoid that the modified local variable is */
-       /* kept on the stack (see stack.c, ICMD_IINC) */
-       stackreq[JAVA_IINC]         = 1;
+       stackreq[JAVA_IINC]         = 0;
        
        stackreq[JAVA_SWAP] = 2;
        stackreq[JAVA_DUP2] = 2;
index 32220a0442426cf385a81c898f86c47da411de56..95bdbe1812cb72ab458b6e564dc6d664ab6c0524 100644 (file)
@@ -30,7 +30,7 @@
    Changes: Christian Thalinger
                        Edwin Steiner
 
-   $Id: jit.h 4476 2006-02-07 16:47:44Z edwin $
+   $Id: jit.h 4524 2006-02-16 19:39:36Z christian $
 
 */
 
@@ -94,7 +94,9 @@ typedef struct subroutineinfo subroutineinfo;
 #define SAVEDVAR   1            /* variable has to survive method invocations */
 #define INMEMORY   2            /* variable stored in memory                  */
 #define SAVEDTMP   4            /* temporary variable using a saved register  */
-#define TMPARG     8            /* temporary variable using a argument register  */
+#define TMPARG     8            /* temporary variable using a arg register    */
+#define STCOPY    16            /* there is another stackslot alive           */
+                                /* using the same register/memory location    */
 
 /* variable kinds */
 
index c39034347b7826b2a979aebf3ac84103a9e489f3..2b22f3be2dbc86a9f2b2ddc6e2af7ac08ba46ae8 100644 (file)
@@ -30,7 +30,7 @@
             Christian Thalinger
             Christian Ullrich
 
-   $Id: stack.c 4455 2006-02-06 01:02:59Z edwin $
+   $Id: stack.c 4524 2006-02-16 19:39:36Z christian $
 
 */
 
@@ -127,7 +127,7 @@ methodinfo *analyse_stack(methodinfo *m, codegendata *cd, registerdata *rd)
        stackptr      curstack;
        stackptr      new;
        stackptr      copy;
-       int           opcode, i, len, loops;
+       int           opcode, i, j, len, loops;
        int           superblockend, repeat, deadcode;
        instruction  *iptr;
        basicblock   *bptr;
@@ -135,6 +135,12 @@ methodinfo *analyse_stack(methodinfo *m, codegendata *cd, registerdata *rd)
        s4           *s4ptr;
        void        **tptr;
        s4           *argren;
+       s4           *last_store;/* instruction index of last XSTORE */
+                                /* [ local_index * 5 + type ] */
+       s4            last_pei;  /* instruction index of last possible exception */
+                                /* used for conflict resolution for copy        */
+                             /* elimination (XLOAD, IINC, XSTORE) */
+       s4            last_dupx;
 
        builtintable_entry *bte;
        unresolved_method  *um;
@@ -147,6 +153,8 @@ methodinfo *analyse_stack(methodinfo *m, codegendata *cd, registerdata *rd)
        argren = DMNEW(s4, cd->maxlocals);   /* table for argument renaming       */
        for (i = 0; i < cd->maxlocals; i++)
                argren[i] = i;
+
+       last_store = DMNEW(s4 , cd->maxlocals * 5);
        
        new = m->stack;
        loops = 0;
@@ -276,6 +284,12 @@ methodinfo *analyse_stack(methodinfo *m, codegendata *cd, registerdata *rd)
                                iptr = bptr->iinstr;
                                b_index = bptr - m->basicblocks;
 
+                               last_pei = -1;
+                               last_dupx = -1;
+                               for( i = 0; i < cd->maxlocals; i++)
+                                       for( j = 0; j < 5; j++)
+                                               last_store[5 * i + j] = -1;
+
                                bptr->stack = new;
 
                                while (--len >= 0)  {
@@ -1101,6 +1115,8 @@ methodinfo *analyse_stack(methodinfo *m, codegendata *cd, registerdata *rd)
                                                                count_store_depth[i]++;
                                                }
 #endif
+                                               last_store[5 * iptr->op1 + TYPE_INT] = bptr->icount - len - 1;
+
                                                copy = curstack;
                                                i = stackdepth - 1;
                                                while (copy) {
@@ -1112,12 +1128,6 @@ methodinfo *analyse_stack(methodinfo *m, codegendata *cd, registerdata *rd)
                                                        i--;
                                                        copy = copy->prev;
                                                }
-
-                                               /* allocate a dummy stack slot to keep ISTORE from */
-                                               /* marking its input stack as a LOCALVAR, since we */
-                                               /* change the value of the local variable here.    */
-                                               NEWSTACK0(TYPE_INT);
-                                               POP(TYPE_INT);
                                                
                                                SETDST;
                                                break;
@@ -1152,6 +1162,7 @@ methodinfo *analyse_stack(methodinfo *m, codegendata *cd, registerdata *rd)
                                                        count_store_depth[i]++;
                                        }
 #endif
+                                       /* check for conflicts as described in Figure 5.2 */
                                        copy = curstack->prev;
                                        i = stackdepth - 2;
                                        while (copy) {
@@ -1163,10 +1174,107 @@ methodinfo *analyse_stack(methodinfo *m, codegendata *cd, registerdata *rd)
                                                i--;
                                                copy = copy->prev;
                                        }
-                                       if ((new - curstack) == 1) {
-                                               curstack->varkind = LOCALVAR;
-                                               curstack->varnum = iptr->op1;
-                                       };
+
+                                       /* do not change instack Stackslots */
+                                       /* it won't improve performance if we copy the interface */
+                                       /* at the BB begin or here, and lsra relies that no      */
+                                       /* instack stackslot is marked LOCALVAR */
+                                       if (curstack->varkind == STACKVAR)
+                                               goto _possible_conflict;
+
+                                       /* check for a DUPX,SWAP while the lifetime of curstack */
+                                       /* and as creator curstack */
+                                       if (last_dupx != -1) { 
+                                               /* we have to look at the dst stack of DUPX */
+                                               /* == src Stack of PEI */
+                                               copy = bptr->iinstr[last_dupx].dst;
+                                               /*
+                                               if (last_pei == 0)
+                                                       copy = bptr->instack;
+                                               else
+                                                       copy = bptr->iinstr[last_pei-1].dst;
+                                               */
+                                               if ((copy != NULL) && (curstack <= copy)) {
+                                                       /* curstack alive at or created by DUPX */
+
+                                                       /* TODO:.... */
+                                                       /* now look, if there is a LOCALVAR at anyone of */
+                                                       /* the src stacklots used by DUPX */
+
+                                                       goto _possible_conflict;
+                                               }
+                                       }
+
+                                       /* check for a PEI while the lifetime of curstack */
+                                       if (last_pei != -1) { 
+                                               /* && there are exception handler in this method */
+                                               /* when this is checked prevent ARGVAR from      */
+                                               /* overwriting LOCALVAR!!! */
+
+                                               /* we have to look at the stack _before_ the PEI! */
+                                               /* == src Stack of PEI */
+                                               if (last_pei == 0)
+                                                       copy = bptr->instack;
+                                               else
+                                                       copy = bptr->iinstr[last_pei-1].dst;
+                                               if ((copy != NULL) && (curstack <= copy)) {
+                                                       /* curstack alive at PEI */
+                                                       goto _possible_conflict;
+                                               }
+                                       }
+                                       
+                                       /* check if there is a possible conflicting XSTORE */
+                                       if (last_store[5 * iptr->op1 + opcode - ICMD_ISTORE] != -1) {
+                                               /* we have to look at the stack _before_ the XSTORE! */
+                                               /* == src Stack of XSTORE */
+                                               if (last_store[5 * iptr->op1 + opcode - ICMD_ISTORE] == 0)
+                                                       copy = bptr->instack;
+                                               else
+                                                       copy = bptr->iinstr[last_store[5 * iptr->op1 + opcode - ICMD_ISTORE] - 1].dst;
+                                               if ((copy != NULL) && (curstack <= copy)) {
+                                                       /* curstack alive at Last Store */
+                                                       goto _possible_conflict;
+                                               }
+                                       }
+
+                                       /* check if there is a conflict with a XLOAD */
+                                       /* this is done indirectly by looking if a Stackslot is */
+                                       /* marked LOCALVAR and is live while curstack is live   */
+                                       /* see figure 5.3 */
+
+                                       /* First check "above" stackslots of the instack */
+                                       copy = curstack + 1;
+                                       for(;(copy <= bptr->instack); copy++)
+                                               if ((copy->varkind == LOCALVAR) && (copy->varnum == iptr->op1)) {
+                                                       goto _possible_conflict;
+                                               }
+                                       
+                                       /* "intra" Basic Block Stackslots are allocated above    */
+                                       /* bptr->stack (see doc/stack.txt), so if curstack + 1   */
+                                       /* is an instack, copy could point now to the stackslots */
+                                       /* of an inbetween analysed Basic Block */
+                                       if (copy < bptr->stack)
+                                               copy = bptr->stack;
+                                       while (copy < new) {
+                                               if ((copy->varkind == LOCALVAR) && (copy->varnum == iptr->op1)) {
+                                                       goto _possible_conflict;
+                                               }
+                                               copy++;
+                                       }
+                                       /* no conflict - mark the Stackslot as LOCALVAR */
+                                       curstack->varkind = LOCALVAR;
+                                       curstack->varnum = iptr->op1;
+                                       
+                                       goto _local_join;
+                               _possible_conflict:
+                                       if ((curstack->varkind == LOCALVAR) 
+                                               && (curstack->varnum == iptr->op1)) {
+                                               curstack->varkind = TEMPVAR;
+                                               curstack->varnum = stackdepth-1;
+                                       }
+                               _local_join:
+                                       last_store[5 * iptr->op1 + opcode - ICMD_ISTORE] = bptr->icount - len - 1;
+
                                        STORE(opcode - ICMD_ISTORE);
                                        break;
 
@@ -1510,11 +1618,13 @@ methodinfo *analyse_stack(methodinfo *m, codegendata *cd, registerdata *rd)
                                                        }
                                                }
 #endif
+                                               last_dupx = bptr->icount - len - 1;
                                                COUNT(count_dup_instruction);
                                                DUP;
                                                break;
 
                                        case ICMD_DUP2:
+                                               last_dupx = bptr->icount - len - 1;
                                                REQUIRE_1;
                                                if (IS_2_WORD_TYPE(curstack->type)) {
                                                        /* ..., cat2 */
@@ -1555,10 +1665,12 @@ methodinfo *analyse_stack(methodinfo *m, codegendata *cd, registerdata *rd)
                                                        }
                                                }
 #endif
+                                               last_dupx = bptr->icount - len - 1;
                                                DUP_X1;
                                                break;
 
                                        case ICMD_DUP2_X1:
+                                               last_dupx = bptr->icount - len - 1;
                                                REQUIRE_2;
                                                if (IS_2_WORD_TYPE(curstack->type)) {
                                                        /* ..., ????, cat2 */
@@ -1592,6 +1704,7 @@ methodinfo *analyse_stack(methodinfo *m, codegendata *cd, registerdata *rd)
                                                /* pop 3 push 4 dup */
                                                
                                        case ICMD_DUP_X2:
+                                               last_dupx = bptr->icount - len - 1;
                                                REQUIRE_2;
                                                if (IS_2_WORD_TYPE(curstack->prev->type)) {
                                                        /* ..., cat2, ???? */
@@ -1623,6 +1736,7 @@ methodinfo *analyse_stack(methodinfo *m, codegendata *cd, registerdata *rd)
                                                break;
 
                                        case ICMD_DUP2_X2:
+                                               last_dupx = bptr->icount - len - 1;
                                                REQUIRE_2;
                                                if (IS_2_WORD_TYPE(curstack->type)) {
                                                        /* ..., ????, cat2 */
@@ -1682,6 +1796,7 @@ methodinfo *analyse_stack(methodinfo *m, codegendata *cd, registerdata *rd)
                                                /* pop 2 push 2 swap */
                                                
                                        case ICMD_SWAP:
+                                               last_dupx = bptr->icount - len - 1;
 #ifdef TYPECHECK_STACK_COMPCAT
                                                if (opt_verify) {
                                                        REQUIRE_2;
@@ -2010,6 +2125,9 @@ methodinfo *analyse_stack(methodinfo *m, codegendata *cd, registerdata *rd)
 /*                              {COUNT(count_check_null);} */   
 
                                        _callhandling:
+
+                                               last_pei = bptr->icount - len - 1;
+
                                                i = md->paramcount;
 
                                                if (md->memuse > rd->memuse)
index 0c00a278c16ee743d3e5468223923be92ac3e138..712b3678a6e5b10ee6b608b3df6523189f9c7891 100644 (file)
@@ -28,7 +28,7 @@
 
    Changes: Christian Ullrich
 
-   $Id: stack.h 4483 2006-02-11 21:25:45Z christian $
+   $Id: stack.h 4524 2006-02-16 19:39:36Z christian $
 
 */
 
         curstack = curstack->prev; \
     } while (0)
 
-/*******************************************************
-Quick Fix to prevent dependence problems of local vars
-varnum is not set to the according position within the stack
-like it is done normaly in stack.c
--> if this shows to be a problem this can be solved in all the
-DUP* and SWAP Macros
-TODO: dependences should be prevented as described in the
-CACAO JVM Paper
-Interface Stackslots (STACKVAR) are not allowed to be copied.
-ARGVAR are taken out, too.
-*******************************************************/
+/* Do not copy Interface Stackslots over DUPx, Swaps! */
 #define COPY(s,d) \
     do { \
         (d)->flags = 0; \
         (d)->type = (s)->type; \
-        (d)->varkind = TEMPVAR; \
-        (d)->varnum = 0; \
+               if ( (s)->varkind != STACKVAR) {                \
+                       (d)->varkind = (s)->varkind; \
+                       (d)->varnum = (s)->varnum;       \
+               } else { \
+                       (d)->varkind = TEMPVAR; \
+                       (d)->varnum = 0; \
+               } \
     } while (0)
 
 
@@ -340,10 +335,14 @@ ARGVAR are taken out, too.
         SETDST; \
     } while (0)
 
-/* Same dependency quick fix as at COPY */
+/* Do not copy Interface Stackslots over DUP! */
 #define DUP         {REQUIRE_1; \
-                    NEWSTACK(CURTYPE,TEMPVAR,stackdepth-1);SETDST; \
-                    stackdepth++; INC_LIFETIMES(1);}
+                            if (CURKIND != STACKVAR) { \
+                                                NEWSTACK(CURTYPE,CURKIND,curstack->varnum); \
+                                        } else { \
+                                                NEWSTACK(CURTYPE, TEMPVAR, stackdepth); \
+                                        } \
+                                        SETDST; stackdepth++; INC_LIFETIMES(1);}
 #define SWAP        {REQUIRE_2;COPY(curstack,new);POPANY;COPY(curstack,new+1);POPANY;\
                     new[0].prev=curstack;new[1].prev=new;\
                     curstack=new+1;new+=2;SETDST;}