Merged revisions 7797-7917 via svnmerge from
[cacao.git] / src / vm / jit / codegen-common.c
index bc63d9550039f1f0ab6d44868716813a00264928..cccf3acb10b7939a6b0fa47df146df5c0166a7a0 100644 (file)
@@ -39,7 +39,7 @@
    memory. All functions writing values into the data area return the offset
    relative the begin of the code area (start of procedure).   
 
-   $Id: codegen-common.c 7797 2007-04-23 20:12:39Z michi $
+   $Id: codegen-common.c 7918 2007-05-20 20:42:18Z michi $
 
 */
 
 #include "vm/jit/jit.h"
 #include "vm/jit/md.h"
 #include "vm/jit/replace.h"
+#if defined(ENABLE_SSA)
+# include "vm/jit/optimizing/lsra.h"
+# include "vm/jit/optimizing/ssa.h"
+#endif
 #include "vm/jit/stacktrace.h"
 
 #if defined(ENABLE_INTRP)
 
 /* in this tree we store all method addresses *********************************/
 
-static avl_tree *methodtree = NULL;
-static s4 methodtree_comparator(const void *pc, const void *element);
+static avl_tree_t *methodtree = NULL;
+static s4 methodtree_comparator(const void *treenode, const void *node);
 
 
 /* codegen_init ****************************************************************
@@ -199,16 +203,12 @@ void codegen_setup(jitdata *jd)
 /*     cd->patchrefs      = list_create_dump(OFFSET(patchref, linkage)); */
        cd->patchrefs      = NULL;
        cd->brancheslabel  = list_create_dump(OFFSET(branch_label_ref_t, linkage));
+       cd->listcritical   = list_create_dump(OFFSET(critical_section_ref_t, linkage));
 
        cd->linenumberreferences = NULL;
        cd->linenumbertablesizepos = 0;
        cd->linenumbertablestartpos = 0;
        cd->linenumbertab = 0;
-       
-#if defined(ENABLE_THREADS)
-       cd->threadcritcurrent.next = NULL;
-       cd->threadcritcount = 0;
-#endif
 }
 
 
@@ -251,17 +251,13 @@ static void codegen_reset(jitdata *jd)
 /*     cd->patchrefs       = list_create_dump(OFFSET(patchref, linkage)); */
        cd->patchrefs       = NULL;
        cd->brancheslabel   = list_create_dump(OFFSET(branch_label_ref_t, linkage));
+       cd->listcritical    = list_create_dump(OFFSET(critical_section_ref_t, linkage));
 
        cd->linenumberreferences    = NULL;
        cd->linenumbertablesizepos  = 0;
        cd->linenumbertablestartpos = 0;
        cd->linenumbertab           = 0;
        
-#if defined(ENABLE_THREADS)
-       cd->threadcritcurrent.next = NULL;
-       cd->threadcritcount        = 0;
-#endif
-
        /* We need to clear the mpc and the branch references from all
           basic blocks as they will definitely change. */
 
@@ -563,19 +559,182 @@ void codegen_add_patch_ref(codegendata *cd, functionptr patcher, voidptr ref,
 }
 
 
+/* codegen_critical_section_new ************************************************
+
+   Allocates a new critical-section reference and adds it to the
+   critical-section list.
+
+*******************************************************************************/
+
+#if defined(ENABLE_THREADS)
+void codegen_critical_section_new(codegendata *cd)
+{
+       list_t                 *list;
+       critical_section_ref_t *csr;
+       s4                      mpc;
+
+       /* get the critical section list */
+
+       list = cd->listcritical;
+       
+       /* calculate the current mpc */
+
+       mpc = cd->mcodeptr - cd->mcodebase;
+
+       csr = DNEW(critical_section_ref_t);
+
+       /* We only can set restart right now, as start and end are set by
+          the following, corresponding functions. */
+
+       csr->start   = -1;
+       csr->end     = -1;
+       csr->restart = mpc;
+
+       /* add the branch to the list */
+
+       list_add_last_unsynced(list, csr);
+}
+#endif
+
+
+/* codegen_critical_section_start **********************************************
+
+   Set the start-point of the current critical section (which is the
+   last element of the list).
+
+*******************************************************************************/
+
+#if defined(ENABLE_THREADS)
+void codegen_critical_section_start(codegendata *cd)
+{
+       list_t                 *list;
+       critical_section_ref_t *csr;
+       s4                      mpc;
+
+       /* get the critical section list */
+
+       list = cd->listcritical;
+       
+       /* calculate the current mpc */
+
+       mpc = cd->mcodeptr - cd->mcodebase;
+
+       /* get the current critical section */
+
+       csr = list_last_unsynced(list);
+
+       /* set the start point */
+
+       assert(csr->start == -1);
+
+       csr->start = mpc;
+}
+#endif
+
+
+/* codegen_critical_section_end ************************************************
+
+   Set the end-point of the current critical section (which is the
+   last element of the list).
+
+*******************************************************************************/
+
+#if defined(ENABLE_THREADS)
+void codegen_critical_section_end(codegendata *cd)
+{
+       list_t                 *list;
+       critical_section_ref_t *csr;
+       s4                      mpc;
+
+       /* get the critical section list */
+
+       list = cd->listcritical;
+       
+       /* calculate the current mpc */
+
+       mpc = cd->mcodeptr - cd->mcodebase;
+
+       /* get the current critical section */
+
+       csr = list_last_unsynced(list);
+
+       /* set the end point */
+
+       assert(csr->end == -1);
+
+       csr->end = mpc;
+}
+#endif
+
+
+/* codegen_critical_section_finish *********************************************
+
+   Finish the critical sections, create the critical section nodes for
+   the AVL tree and insert them into the tree.
+
+*******************************************************************************/
+
+#if defined(ENABLE_THREADS)
+static void codegen_critical_section_finish(jitdata *jd)
+{
+       codeinfo    *code;
+       codegendata *cd;
+       list_t                  *list;
+       critical_section_ref_t  *csr;
+       critical_section_node_t *csn;
+
+       /* get required compiler data */
+
+       code = jd->code;
+       cd   = jd->cd;
+
+       /* get the critical section list */
+
+       list = cd->listcritical;
+
+       /* iterate over all critical sections */
+
+       for (csr = list_first_unsynced(list); csr != NULL;
+                csr = list_next_unsynced(list, csr)) {
+               /* check if all points are set */
+
+               assert(csr->start   != -1);
+               assert(csr->end     != -1);
+               assert(csr->restart != -1);
+
+               /* allocate tree node */
+
+               csn = NEW(critical_section_node_t);
+
+               csn->start   = code->entrypoint + csr->start;
+               csn->end     = code->entrypoint + csr->end;
+               csn->restart = code->entrypoint + csr->restart;
+
+               /* insert into the tree */
+
+               critical_section_register(csn);
+       }
+}
+#endif
+
+
 /* methodtree_comparator *******************************************************
 
    Comparator function used for the AVL tree of methods.
 
+   ARGUMENTS:
+      treenode....the node from the tree
+      node........the node to compare to the tree-node
+
 *******************************************************************************/
 
-static s4 methodtree_comparator(const void *pc, const void *element)
+static s4 methodtree_comparator(const void *treenode, const void *node)
 {
        methodtree_element *mte;
        methodtree_element *mtepc;
 
-       mte = (methodtree_element *) element;
-       mtepc = (methodtree_element *) pc;
+       mte   = (methodtree_element *) treenode;
+       mtepc = (methodtree_element *) node;
 
        /* compare both startpc and endpc of pc, even if they have the same value,
           otherwise the avl_probe sometimes thinks the element is already in the
@@ -777,7 +936,6 @@ void codegen_finish(jitdata *jd)
        s4           alignedmcodelen;
        jumpref     *jr;
        u1          *epoint;
-       s4           extralen;
        s4           alignedlen;
 
        /* get required compiler data */
@@ -795,12 +953,6 @@ void codegen_finish(jitdata *jd)
 
        mcodelen = (s4) (cd->mcodeptr - cd->mcodebase);
 
-#if defined(ENABLE_THREADS)
-       extralen = sizeof(critical_section_node_t) * cd->threadcritcount;
-#else
-       extralen = 0;
-#endif
-
 #if defined(ENABLE_STATISTICS)
        if (opt_stat) {
                count_code_len += mcodelen;
@@ -830,7 +982,7 @@ void codegen_finish(jitdata *jd)
        /* allocate new memory */
 
        code->mcodelength = mcodelen + cd->dseglen;
-       code->mcode       = CNEW(u1, alignedlen + extralen);
+       code->mcode       = CNEW(u1, alignedlen);
 
        /* set the entrypoint of the method */
        
@@ -928,20 +1080,9 @@ void codegen_finish(jitdata *jd)
 #endif
 
 #if defined(ENABLE_THREADS)
-       {
-               critical_section_node_t *n = (critical_section_node_t *) ((ptrint) code->mcode + alignedlen);
-               s4 i;
-               codegen_critical_section_t *nt = cd->threadcrit;
-
-               for (i = 0; i < cd->threadcritcount; i++) {
-                       n->mcodebegin = (u1 *) (ptrint) code->mcode + nt->mcodebegin;
-                       n->mcodeend = (u1 *) (ptrint) code->mcode + nt->mcodeend;
-                       n->mcoderestart = (u1 *) (ptrint) code->mcode + nt->mcoderestart;
-                       critical_register_critical_section(n);
-                       n++;
-                       nt = nt->next;
-               }
-       }
+       /* create cirtical sections */
+
+       codegen_critical_section_finish(jd);
 #endif
 
        /* flush the instruction and data caches */
@@ -1083,7 +1224,7 @@ void codegen_generate_stub_builtin(builtintable_entry *bte)
 
 #if defined(ENABLE_STATISTICS)
        if (opt_stat)
-               count_nstub_len += code->mcodelength;
+               size_stub_native += code->mcodelength;
 #endif
 
        /* release memory */
@@ -1198,8 +1339,10 @@ codeinfo *codegen_generate_stub_native(methodinfo *m, functionptr f)
        codegen_finish(jd);
 
 #if defined(ENABLE_STATISTICS)
+       /* must be done after codegen_finish() */
+
        if (opt_stat)
-               count_nstub_len += code->mcodelength;
+               size_stub_native += code->mcodelength;
 #endif
 
 #if !defined(NDEBUG)
@@ -1363,7 +1506,7 @@ void codegen_start_native_call(u1 *datasp, u1 *pv, u1 *sp, u1 *ra)
 
        stacktrace_create_native_stackframeinfo(sfi, pv, sp, ra);
 
-#if defined(ENABLE_JAVASE)
+#if defined(ENABLE_JNI)
        /* add current JNI local references table to this thread */
 
        lrt->capacity    = LOCALREFTABLE_CAPACITY;
@@ -1398,7 +1541,7 @@ java_objectheader *codegen_finish_native_call(u1 *datasp)
 {
        stackframeinfo     *sfi;
        stackframeinfo    **psfi;
-#if defined(ENABLE_JAVASE)
+#if defined(ENABLE_JNI)
        localref_table     *lrt;
        localref_table     *plrt;
        s4                  localframes;
@@ -1421,7 +1564,7 @@ java_objectheader *codegen_finish_native_call(u1 *datasp)
 
        *psfi = sfi->prev;
 
-#if defined(ENABLE_JAVASE)
+#if defined(ENABLE_JNI)
        /* release JNI local references tables for this thread */
 
        lrt = LOCALREFTABLE;
@@ -1559,28 +1702,95 @@ s4 codegen_reg_of_dst(jitdata *jd, instruction *iptr, s4 tempregnum)
 }
 
 
-#if defined(ENABLE_THREADS)
-void codegen_threadcritrestart(codegendata *cd, int offset)
-{
-       cd->threadcritcurrent.mcoderestart = offset;
-}
+/* codegen_emit_phi_moves ****************************************************
 
+   Emits phi moves at the end of the basicblock.
+
+*******************************************************************************/
 
-void codegen_threadcritstart(codegendata *cd, int offset)
+#if defined(ENABLE_SSA)
+void codegen_emit_phi_moves(jitdata *jd, basicblock *bptr)
 {
-       cd->threadcritcurrent.mcodebegin = offset;
-}
+       int lt_d,lt_s,i;
+       lsradata *ls;
+       codegendata *cd;
+       varinfo *s, *d;
+       instruction tmp_i;
 
+       cd = jd->cd;
+       ls = jd->ls;
 
-void codegen_threadcritstop(codegendata *cd, int offset)
-{
-       cd->threadcritcurrent.next = cd->threadcrit;
-       cd->threadcritcurrent.mcodeend = offset;
-       cd->threadcrit = DNEW(codegen_critical_section_t);
-       *(cd->threadcrit) = cd->threadcritcurrent;
-       cd->threadcritcount++;
-}
+       MCODECHECK(512);
+
+       /* Moves from phi functions with highest indices have to be */
+       /* inserted first, since this is the order as is used for   */
+       /* conflict resolution */
+
+       for(i = ls->num_phi_moves[bptr->nr] - 1; i >= 0 ; i--) {
+               lt_d = ls->phi_moves[bptr->nr][i][0];
+               lt_s = ls->phi_moves[bptr->nr][i][1];
+#if defined(SSA_DEBUG_VERBOSE)
+               if (compileverbose)
+                       printf("BB %3i Move %3i <- %3i ", bptr->nr, lt_d, lt_s);
 #endif
+               if (lt_s == UNUSED) {
+#if defined(SSA_DEBUG_VERBOSE)
+               if (compileverbose)
+                       printf(" ... not processed \n");
+#endif
+                       continue;
+               }
+                       
+               d = VAR(ls->lifetime[lt_d].v_index);
+               s = VAR(ls->lifetime[lt_s].v_index);
+               
+
+               if (d->type == -1) {
+#if defined(SSA_DEBUG_VERBOSE)
+                       if (compileverbose)
+                               printf("...returning - phi lifetimes where joined\n");
+#endif
+                       return;
+               }
+
+               if (s->type == -1) {
+#if defined(SSA_DEBUG_VERBOSE)
+                       if (compileverbose)
+                               printf("...returning - phi lifetimes where joined\n");
+#endif
+                       return;
+               }
+
+               tmp_i.opc = 0;
+               tmp_i.s1.varindex = ls->lifetime[lt_s].v_index;
+               tmp_i.dst.varindex = ls->lifetime[lt_d].v_index;
+               emit_copy(jd, &tmp_i);
+
+#if defined(SSA_DEBUG_VERBOSE)
+               if (compileverbose) {
+                       if (IS_INMEMORY(d->flags) && IS_INMEMORY(s->flags)) {
+                               /* mem -> mem */
+                               printf("M%3i <- M%3i",d->vv.regoff,s->vv.regoff);
+                       }
+                       else if (IS_INMEMORY(s->flags)) {
+                               /* mem -> reg */
+                               printf("R%3i <- M%3i",d->vv.regoff,s->vv.regoff);
+                       }
+                       else if (IS_INMEMORY(d->flags)) {
+                               /* reg -> mem */
+                               printf("M%3i <- R%3i",d->vv.regoff,s->vv.regoff);
+                       }
+                       else {
+                               /* reg -> reg */
+                               printf("R%3i <- R%3i",d->vv.regoff,s->vv.regoff);
+                       }
+                       printf("\n");
+               }
+#endif /* defined(SSA_DEBUG_VERBOSE) */
+       }
+}
+#endif /* defined(ENABLE_SSA) */
+
 
 
 /*