Also set xcheckarefs back to null.
[cacao.git] / jit / codegen.inc
index 77b7afaf62aa5e144b5910a646aeff06accdee8b..7098b7155c969c07d6919bd53fd47af4b273bad3 100644 (file)
    memory. All functions writing values into the data area return the offset
    relative the begin of the code area (start of procedure).   
 
-   $Id: codegen.inc 883 2004-01-14 12:42:52Z stefan $
+   $Id: codegen.inc 1116 2004-06-02 10:34:31Z twisti $
 
 */
 
 
 #include <string.h>
 #include "toolbox/memory.h"
-#include "toolbox/loging.h"
+#include "toolbox/logging.h"
+#include "toolbox/avl.h"
 #include "threads/thread.h"
 
 
@@ -63,7 +64,7 @@
 
 struct threadcritnodetemp {
        struct threadcritnodetemp *next;
-       int mcodebegin, mcodeend;
+       int mcodebegin, mcodeend, mcoderestart;
 };
 
 #define MCODEINITSIZE (1<<15)       /* 32 Kbyte code area initialization size */
@@ -85,6 +86,11 @@ static branchref *xcheckarefs;      /* list of array size check branches      */
 static branchref *xnullrefs;        /* list of null check branches            */
 static branchref *xcastrefs;        /* list of cast check branches            */
 static branchref *xdivrefs;         /* list of divide by zero branches        */
+static branchref *xexceptionrefs;   /* list of exception branches             */
+static linenumberref *linenumberreferences; /*list of line numbers and the program counters of their first instruction*/
+static s4 linenumbertablesizepos;
+static s4 linenumbertablestartpos;
+static s4 linenumbertab;
 
 static struct threadcritnodetemp *threadcrit;
                                     /* List of critical code regions          */
@@ -99,7 +105,11 @@ static void codegen_finish();       /* makes code and data area permanent and */
                                     /* updates branch references to code/data */
 
 static s4 dseg_adds4(s4 value);         /* adds an int to data area           */
+
+#if !defined(__I386__)
 static s4 dseg_adds8(s8 value);         /* adds an long to data area          */
+#endif
+
 static s4 dseg_addfloat (float value);  /* adds an float to data area         */
 static s4 dseg_adddouble(double value); /* adds an double to data area        */
 
@@ -112,18 +122,33 @@ static s4 dseg_adddouble(double value); /* adds an double to data area        */
 static void dseg_addtarget(basicblock *target);
 static void dseg_adddata(u1 *ptr);
 static void codegen_addreference(basicblock *target, void *branchptr);
-static void codegen_addxboundrefs(void *branchptr);
+static void codegen_addxboundrefs(void *branchptr, s4 reg);
 static void codegen_addxnullrefs(void *branchptr);
 static void codegen_addxcastrefs(void *branchptr);
 static void codegen_addxdivrefs(void *branchptr);
+static void codegen_addxexceptionrefs(void *branchptr);
+static void codegen_threadcritrestart(int offset);
 static void codegen_threadcritstart(int offset);
 static void codegen_threadcritstop(int offset);
 
+#if defined(__I386__) || defined(__X86_64__)
+typedef struct _methodtree_element methodtree_element;
+
+struct _methodtree_element {
+       void *startpc;
+       void *endpc;
+};
+
+static struct avl_table *methodtree;
+static int methodtree_comparator(const void *pc, const void *element,
+                                                                void *param);
+#endif
+
 void dseg_display(s4 *s4ptr);
 
 
 
-/* codegen_init allocates and initialises code area, data area and references   */
+/* codegen_init allocates and initialises code area, data area and references */
 
 void codegen_init()
 {
@@ -140,12 +165,22 @@ void codegen_init()
 
        dseglen = 0;
 
+       linenumberreferences = NULL;
+       linenumbertablesizepos = 0;
+       linenumbertablestartpos = 0;
+       linenumbertab = 0;
        jumpreferences = NULL;
        datareferences = NULL;
        xboundrefs = NULL;
+       xcheckarefs = NULL;
        xnullrefs = NULL;
        xcastrefs = NULL;
        xdivrefs = NULL;
+       xexceptionrefs = NULL;
+
+#if defined(__I386__) || defined(__X86_64__)
+       methodtree = avl_create(methodtree_comparator, NULL, NULL);
+#endif
 
 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
        threadcritcurrent.next = NULL;
@@ -155,7 +190,7 @@ void codegen_init()
 
 
 
-/* codegen_close releases temporary code and data area                          */
+/* codegen_close releases temporary code and data area                        */
 
 void codegen_close()
 {
@@ -172,7 +207,7 @@ void codegen_close()
 
 
 
-/* codegen_increase doubles code area                                           */
+/* codegen_increase doubles code area                                         */
 
 static s4 *codegen_increase(u1 *codeptr)
 {
@@ -224,6 +259,7 @@ static s4 dseg_adds4(s4 value)
 
 
 
+#if !defined(__I386__)
 static s4 dseg_adds8_increase(s8 value)
 {
        dseg_increase();
@@ -232,7 +268,6 @@ static s4 dseg_adds8_increase(s8 value)
 }
 
 
-
 static s4 dseg_adds8(s8 value)
 {
        s8 *dataptr;
@@ -244,7 +279,7 @@ static s4 dseg_adds8(s8 value)
        *dataptr = value;
        return -dseglen;
 }
-
+#endif
 
 
 static s4 dseg_addfloat_increase(float value)
@@ -296,7 +331,7 @@ static s4 dseg_adddouble(double value)
 static void dseg_addtarget(basicblock *target)
 {
        jumpref *jr = DNEW(jumpref);
-
+       
        jr->tablepos = dseg_addaddress(NULL);
        jr->target = target;
        jr->next = jumpreferences;
@@ -314,7 +349,26 @@ static void dseg_adddata(u1 *ptr)
        datareferences = dr;
 }
 
+static void dseg_addlinenumbertablesize() {
+#ifdef __ALPHA__
+       dseg_adds4(0); /*PADDING*/
+#endif
+       linenumbertablesizepos=dseg_addaddress(NULL); /*it could be considered to use adds4 here, to avoid 1 double word padding on ALPHA */
+
+       linenumbertablestartpos=dseg_addaddress(NULL);
+#ifdef __ALPHA__
+       dseg_adds4(0); /*PADDING*/
+#endif
+}
 
+static void dseg_addlinenumber(u2 linenumber,u1 *ptr) {
+       linenumberref *lr=DNEW(linenumberref);
+       lr->linenumber=linenumber;
+       lr->tablepos=0;
+       lr->targetmpc=(ptr-mcodebase);
+       lr->next=linenumberreferences;
+       linenumberreferences=lr;
+}
 
 static void codegen_addreference(basicblock *target, void *branchptr)
 {
@@ -334,13 +388,14 @@ static void codegen_addreference(basicblock *target, void *branchptr)
 
 
 
-static void codegen_addxboundrefs(void *branchptr)
+static void codegen_addxboundrefs(void *branchptr, s4 reg)
 {
        s4 branchpos = (u1*) branchptr - mcodebase;
 
        branchref *br = DNEW(branchref);
 
        br->branchpos = branchpos;
+       br->reg = reg;
        br->next = xboundrefs;
        xboundrefs = br;
 }
@@ -385,6 +440,17 @@ static void codegen_addxcastrefs(void *branchptr)
 }
 
 
+static void codegen_addxexceptionrefs(void *branchptr)
+{
+       s4 branchpos = (u1*) branchptr - mcodebase;
+
+       branchref *br = DNEW(branchref);
+
+       br->branchpos = branchpos;
+       br->next = xexceptionrefs;
+       xexceptionrefs = br;
+}
+
 
 static void codegen_addxdivrefs(void *branchptr)
 {
@@ -398,6 +464,86 @@ static void codegen_addxdivrefs(void *branchptr)
 }
 
 
+static void codegen_createlinenumbertable() {
+#ifdef __I386__
+       /*log_text("codegen_createlinnumbertable");*/
+       {
+               linenumberref *lr;
+               for (lr=linenumberreferences;lr!=NULL;lr=lr->next) {
+                       /*log_text("Adding line number entry");*/
+                       lr->tablepos=dseg_addaddress(NULL);
+                       if (linenumbertab==0) linenumbertab=lr->tablepos;
+                       dseg_addaddress(lr->linenumber);
+               }
+       }
+#endif
+}
+
+
+#if defined(__I386__) || defined(__X86_64__)
+static int methodtree_comparator(const void *pc, const void *element,
+                                                                void *param)
+{
+       methodtree_element *mtepc;
+       methodtree_element *mte;
+
+       mtepc = (methodtree_element *) pc;
+       mte = (methodtree_element *) element;
+
+       if (mte->startpc <= mtepc->startpc && mtepc->startpc <= mte->endpc) {
+               return 0;
+
+       } else if (mtepc->startpc < mte->startpc) {
+               return -1;
+
+       } else {
+               return 1;
+       }
+}
+
+
+#if 0
+void *codegen_findmethod1(void *pc)
+{
+       void * retVal=findmethod(pc);
+       methodinfo **ma=(methodinfo**)retVal;
+       methodinfo *m=ma[-1];
+       if (m)
+               if (m->name)
+                       utf_display(m->name);
+               else 
+                       log_text("No Name");
+       else log_text("No methodinfo");
+       return retVal;
+}
+#endif
+
+void *codegen_findmethod(void *pc)
+{
+#if 1
+       return findmethod(pc);
+#else
+       methodtree_element *mtepc;
+       methodtree_element *mte;
+
+       mtepc = NEW(methodtree_element);
+       mtepc->startpc = pc;
+
+       mte = avl_find(methodtree, mtepc);
+
+       FREE(mtepc, methodtree_element);
+
+/*     if (!mte) */
+/*             throw_cacao_exception_exit(string_java_lang_InternalError, "cannot find function"); */
+
+       fprintf(stderr, "mte=%p\n", mte);
+       fprintf(stderr, "startpc=%p, endpc=%p\n", mte->startpc, mte->endpc);
+
+       return mte->startpc;
+#endif
+}
+#endif
+
 
 static void codegen_finish(int mcodelen)
 {
@@ -415,13 +561,13 @@ static void codegen_finish(int mcodelen)
 
        dseglen = ALIGN(dseglen, MAX_ALIGN);
 
-       method -> mcodelength = mcodelen + dseglen;
-       method -> mcode = CNEW(u1, mcodelen + dseglen + extralen);
+       method->mcodelength = mcodelen + dseglen;
+       method->mcode = CNEW(u1, mcodelen + dseglen + extralen);
 
-       memcpy ( method->mcode, dsegtop - dseglen, dseglen);
-       memcpy ( method->mcode + dseglen, mcodebase, mcodelen);
+       memcpy(method->mcode, dsegtop - dseglen, dseglen);
+       memcpy(method->mcode + dseglen, mcodebase, mcodelen);
 
-       method -> entrypoint = epoint = (u1*) (method->mcode + dseglen);
+       method->entrypoint = epoint = (u1 *) (method->mcode + dseglen);
 
        /* jump table resolving */
        jr = jumpreferences;
@@ -430,12 +576,49 @@ static void codegen_finish(int mcodelen)
            jr = jr->next;
        }
 
+#ifdef __I386__
+       /* line number table resolving */
+       {
+               linenumberref *lr;
+               #if POINTERSIZE == 8
+                       s8  lrtlen=0;
+               #else
+                       s4  lrtlen=0;
+               #endif
+
+               for (lr=linenumberreferences;lr!=NULL;lr=lr->next) {
+                       lrtlen++;
+                       *((void**)(epoint+lr->tablepos))=epoint+lr->targetmpc;
+                       /*log_text("resolving line number information");*/
+               }
+               
+               *((void**)(epoint+linenumbertablestartpos))=epoint+linenumbertab;
+#if POINTERSIZE == 8
+               *((s8*)(epoint+linenumbertablesizepos))=lrtlen;
+#else
+               *((s4*)(epoint+linenumbertablesizepos))=lrtlen;
+#endif
+
+       }
+#endif
 #if defined(__I386__) || defined(__X86_64__)
        {
                dataref *dr;
-               /* add method into datastructure to find the entrypoint */
+#if 1
+               /* add method into methodtree to find the entrypoint */
                addmethod(method->entrypoint, method->entrypoint + mcodelen);
-        
+#else
+               methodtree_element *mte;
+               methodtree_element *p;
+
+               mte = NEW(methodtree_element);
+               mte->startpc = method->entrypoint;
+               mte->endpc = method->entrypoint + mcodelen;
+
+               p = avl_insert(methodtree, mte);
+        printf("p=%p\n", p);
+#endif
+
                /* data segment references resolving */
                dr = datareferences;
                while (dr != NULL) {
@@ -445,6 +628,7 @@ static void codegen_finish(int mcodelen)
        }
 #endif
 
+
 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
        {
                threadcritnode *n = (threadcritnode*) (method->mcode + mcodelen + dseglen);
@@ -455,6 +639,7 @@ static void codegen_finish(int mcodelen)
                {
                        n->mcodebegin = method->mcode + nt->mcodebegin;
                        n->mcodeend = method->mcode + nt->mcodeend;
+                       n->mcoderestart = method->mcode + nt->mcoderestart;
                        thread_registercritical(n);
                        n++;
                        nt = nt->next;
@@ -477,6 +662,11 @@ void dseg_display(s4 *s4ptr)
 }
 
 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
+void codegen_threadcritrestart(int offset)
+{
+       threadcritcurrent.mcoderestart = offset;
+}
+
 void codegen_threadcritstart(int offset)
 {
        threadcritcurrent.mcodebegin = offset;