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 ****************************************************************
/* 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
}
/* 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. */
}
+/* 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
s4 alignedmcodelen;
jumpref *jr;
u1 *epoint;
- s4 extralen;
s4 alignedlen;
/* get required compiler data */
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;
/* 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 */
#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 */
#if defined(ENABLE_STATISTICS)
if (opt_stat)
- count_nstub_len += code->mcodelength;
+ size_stub_native += code->mcodelength;
#endif
/* release memory */
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)
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;
{
stackframeinfo *sfi;
stackframeinfo **psfi;
-#if defined(ENABLE_JAVASE)
+#if defined(ENABLE_JNI)
localref_table *lrt;
localref_table *plrt;
s4 localframes;
*psfi = sfi->prev;
-#if defined(ENABLE_JAVASE)
+#if defined(ENABLE_JNI)
/* release JNI local references tables for this thread */
lrt = LOCALREFTABLE;
}
-#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) */
+
/*