* src/vm/jit/dseg.c (dseg_addlinenumber_inline_start): Read inline
[cacao.git] / src / vm / jit / dseg.c
index cfe121ef282eb08534ce011f0db82d2d90e7a220..2c08e8b66d621ad215dfccb3b5fbaece7860d10d 100644 (file)
@@ -31,7 +31,7 @@
             Joseph Wenninger
                        Edwin Steiner
 
-   $Id: dseg.c 4734 2006-04-05 09:57:55Z edwin $
+   $Id: dseg.c 5834 2006-10-26 11:23:00Z edwin $
 
 */
 
 
 #include <assert.h>
 
+#include "vm/options.h"
 #include "vm/types.h"
 
 #include "mm/memory.h"
 #include "vm/jit/codegen-common.h"
 
 
-/* desg_increase ***************************************************************
 
-   Doubles data area.
+/* dseg_finish *****************************************************************
+
+   Fills the data segment with the values stored.
 
 *******************************************************************************/
 
-void dseg_increase(codegendata *cd)
+void dseg_finish(jitdata *jd)
 {
-       u1 *newstorage;
+       codeinfo    *code;
+       codegendata *cd;
+       dsegentry   *de;
+
+       /* get required compiler data */
+
+       code = jd->code;
+       cd   = jd->cd;
 
-       newstorage = DMNEW(u1, cd->dsegsize * 2);
+       /* process all data segment entries */
 
-       MCOPY(newstorage + cd->dsegsize, cd->dsegtop - cd->dsegsize, u1,
-                 cd->dsegsize);
+       for (de = cd->dseg; de != NULL; de = de->next) {
+               switch (de->type) {
+               case TYPE_INT:
+                       *((s4 *)     (code->entrypoint + de->disp)) = de->val.i;
+                       break;
 
-       cd->dsegtop   = newstorage;
-       cd->dsegsize *= 2;
-       cd->dsegtop  += cd->dsegsize;
+               case TYPE_LNG:
+                       *((s8 *)     (code->entrypoint + de->disp)) = de->val.l;
+                       break;
+
+               case TYPE_FLT:
+                       *((float *)  (code->entrypoint + de->disp)) = de->val.f;
+                       break;
+
+               case TYPE_DBL:
+                       *((double *) (code->entrypoint + de->disp)) = de->val.d;
+                       break;
+
+               case TYPE_ADR:
+                       *((void **)  (code->entrypoint + de->disp)) = de->val.a;
+                       break;
+               }
+       }
 }
 
 
-s4 dseg_adds4_increase(codegendata *cd, s4 value)
+static s4 dseg_find_s4(codegendata *cd, s4 value)
 {
-       dseg_increase(cd);
+       dsegentry *de;
+
+       /* search all data segment entries for a matching entry */
+
+       for (de = cd->dseg; de != NULL; de = de->next) {
+               if (IS_INT_TYPE(de->type))
+                       if (de->flags & DSEG_FLAG_READONLY)
+                               if (de->val.i == value)
+                                       return de->disp;
+       }
 
-       *((s4 *) (cd->dsegtop - cd->dseglen)) = value;
+       /* no matching entry was found */
 
-       return -(cd->dseglen);
+       return 0;
 }
 
 
-s4 dseg_adds4(codegendata *cd, s4 value)
+static s4 dseg_find_s8(codegendata *cd, s8 value)
 {
-       s4 *dataptr;
+       dsegentry *de;
+
+       /* search all data segment entries for a matching entry */
+
+       for (de = cd->dseg; de != NULL; de = de->next) {
+               if (IS_LNG_TYPE(de->type))
+                       if (de->flags & DSEG_FLAG_READONLY)
+                               if (de->val.l == value)
+                                       return de->disp;
+       }
+
+       /* no matching entry was found */
+
+       return 0;
+}
+
+
+static s4 dseg_find_float(codegendata *cd, float value)
+{
+       dsegentry *de;
+
+       /* search all data segment entries for a matching entry */
+
+       for (de = cd->dseg; de != NULL; de = de->next) {
+               if (IS_FLT_TYPE(de->type))
+                       if (de->flags & DSEG_FLAG_READONLY)
+                               if (de->val.f == value)
+                                       return de->disp;
+       }
+
+       /* no matching entry was found */
+
+       return 0;
+}
+
+
+static s4 dseg_find_double(codegendata *cd, double value)
+{
+       dsegentry *de;
+
+       /* search all data segment entries for a matching entry */
+
+       for (de = cd->dseg; de != NULL; de = de->next) {
+               if (IS_DBL_TYPE(de->type))
+                       if (de->flags & DSEG_FLAG_READONLY)
+                               if (de->val.d == value)
+                                       return de->disp;
+       }
+
+       /* no matching entry was found */
+
+       return 0;
+}
+
+
+static s4 dseg_find_address(codegendata *cd, void *value)
+{
+       dsegentry *de;
+
+       /* search all data segment entries for a matching entry */
+
+       for (de = cd->dseg; de != NULL; de = de->next) {
+               if (IS_ADR_TYPE(de->type))
+                       if (de->flags & DSEG_FLAG_READONLY)
+                               if (de->val.a == value)
+                                       return de->disp;
+       }
+
+       /* no matching entry was found */
+
+       return 0;
+}
+
+
+/* dseg_add_s4_intern **********************************************************
+
+   Internal function to add an s4 value to the data segment.
+
+*******************************************************************************/
+
+static s4 dseg_add_s4_intern(codegendata *cd, s4 value, u4 flags)
+{
+       dsegentry *de;
+
+       /* Increase data segment size, which is also the displacement into
+          the data segment. */
 
        cd->dseglen += 4;
-       dataptr = (s4 *) (cd->dsegtop - cd->dseglen);
 
-       if (cd->dseglen > cd->dsegsize)
-               return dseg_adds4_increase(cd, value);
+       /* allocate new entry */
+
+       de = DNEW(dsegentry);
 
-       *dataptr = value;
+       de->type  = TYPE_INT;
+       de->flags = flags;
+       de->disp  = -(cd->dseglen);
+       de->val.i = value;
+       de->next  = cd->dseg;
 
-       return -(cd->dseglen);
+       /* insert into the chain */
+
+       cd->dseg = de;
+
+       return de->disp;
+}
+
+
+/* dseg_add_unique_s4 **********************************************************
+
+   Adds uniquely an s4 value to the data segment.
+
+*******************************************************************************/
+
+s4 dseg_add_unique_s4(codegendata *cd, s4 value)
+{
+       s4 disp;
+
+       disp = dseg_add_s4_intern(cd, value, DSEG_FLAG_UNIQUE);
+
+       return disp;
 }
 
 
-s4 dseg_adds8_increase(codegendata *cd, s8 value)
+/* dseg_add_s4 *****************************************************************
+
+   Adds an s4 value to the data segment. It tries to reuse previously
+   added values.
+
+*******************************************************************************/
+
+s4 dseg_add_s4(codegendata *cd, s4 value)
 {
-       dseg_increase(cd);
+       s4 disp;
+
+       /* search the data segment if the value is already stored */
+
+       disp = dseg_find_s4(cd, value);
 
-       *((s8 *) (cd->dsegtop - cd->dseglen)) = value;
+       if (disp != 0)
+               return disp;
+               
+       disp = dseg_add_s4_intern(cd, value, DSEG_FLAG_READONLY);
 
-       return -(cd->dseglen);
+       return disp;
 }
 
 
-s4 dseg_adds8(codegendata *cd, s8 value)
+/* dseg_add_s8_intern **********************************************************
+
+   Internal function to add an s8 value to the data segment.
+
+*******************************************************************************/
+
+static s4 dseg_add_s8_intern(codegendata *cd, s8 value, u4 flags)
 {
-       s8 *dataptr;
+       dsegentry *de;
+
+       /* Increase data segment size, which is also the displacement into
+          the data segment. */
 
        cd->dseglen = ALIGN(cd->dseglen + 8, 8);
-       dataptr = (s8 *) (cd->dsegtop - cd->dseglen);
 
-       if (cd->dseglen > cd->dsegsize)
-               return dseg_adds8_increase(cd, value);
+       /* allocate new entry */
+
+       de = DNEW(dsegentry);
+
+       de->type  = TYPE_LNG;
+       de->flags = flags;
+       de->disp  = -(cd->dseglen);
+       de->val.l = value;
+       de->next  = cd->dseg;
+
+       /* insert into the chain */
+
+       cd->dseg = de;
+
+       return de->disp;
+}
+
+
+/* dseg_add_unique_s8 **********************************************************
+
+   Adds uniquely an s8 value to the data segment.
+
+*******************************************************************************/
+
+s4 dseg_add_unique_s8(codegendata *cd, s8 value)
+{
+       s4 disp;
 
-       *dataptr = value;
+       disp = dseg_add_s8_intern(cd, value, DSEG_FLAG_UNIQUE);
 
-       return -(cd->dseglen);
+       return disp;
 }
 
 
-s4 dseg_addfloat_increase(codegendata *cd, float value)
+/* dseg_add_s8 *****************************************************************
+
+   Adds an s8 value to the data segment. It tries to reuse previously
+   added values.
+
+*******************************************************************************/
+
+s4 dseg_add_s8(codegendata *cd, s8 value)
 {
-       dseg_increase(cd);
+       s4 disp;
+
+       /* search the data segment if the value is already stored */
+
+       disp = dseg_find_s8(cd, value);
 
-       *((float *) (cd->dsegtop - cd->dseglen)) = value;
+       if (disp != 0)
+               return disp;
+               
+       disp = dseg_add_s8_intern(cd, value, DSEG_FLAG_READONLY);
 
-       return -(cd->dseglen);
+       return disp;
 }
 
 
-s4 dseg_addfloat(codegendata *cd, float value)
+/* dseg_add_float_intern *******************************************************
+
+   Internal function to add a float value to the data segment.
+
+*******************************************************************************/
+
+static s4 dseg_add_float_intern(codegendata *cd, float value, u4 flags)
 {
-       float *dataptr;
+       dsegentry *de;
+               
+       /* Increase data segment size, which is also the displacement into
+          the data segment. */
 
        cd->dseglen += 4;
-       dataptr = (float *) (cd->dsegtop - cd->dseglen);
 
-       if (cd->dseglen > cd->dsegsize)
-               return dseg_addfloat_increase(cd, value);
+       /* allocate new entry */
+
+       de = DNEW(dsegentry);
+
+       de->type  = TYPE_FLT;
+       de->flags = flags;
+       de->disp  = -(cd->dseglen);
+       de->val.f = value;
+       de->next  = cd->dseg;
+
+       /* insert into the chain */
 
-       *dataptr = value;
+       cd->dseg = de;
 
-       return -(cd->dseglen);
+       return de->disp;
 }
 
 
-s4 dseg_adddouble_increase(codegendata *cd, double value)
+/* dseg_add_unique_float *******************************************************
+
+   Adds uniquely an float value to the data segment.
+
+*******************************************************************************/
+
+s4 dseg_add_unique_float(codegendata *cd, float value)
 {
-       dseg_increase(cd);
+       s4 disp;
 
-       *((double *) (cd->dsegtop - cd->dseglen)) = value;
+       disp = dseg_add_float_intern(cd, value, DSEG_FLAG_UNIQUE);
 
-       return -(cd->dseglen);
+       return disp;
 }
 
 
-s4 dseg_adddouble(codegendata *cd, double value)
+/* dseg_add_float **************************************************************
+
+   Adds an float value to the data segment. It tries to reuse
+   previously added values.
+
+*******************************************************************************/
+
+s4 dseg_add_float(codegendata *cd, float value)
+{
+       s4 disp;
+
+       /* search the data segment if the value is already stored */
+
+       disp = dseg_find_float(cd, value);
+
+       if (disp != 0)
+               return disp;
+               
+       disp = dseg_add_float_intern(cd, value, DSEG_FLAG_READONLY);
+
+       return disp;
+}
+
+
+/* dseg_add_double_intern ******************************************************
+
+   Internal function to add a double value to the data segment.
+
+*******************************************************************************/
+
+static s4 dseg_add_double_intern(codegendata *cd, double value, u4 flags)
+{
+       dsegentry *de;
+               
+       /* Increase data segment size, which is also the displacement into
+          the data segment. */
+
+       cd->dseglen = ALIGN(cd->dseglen + 8, 8);
+
+       /* allocate new entry */
+
+       de = DNEW(dsegentry);
+
+       de->type  = TYPE_DBL;
+       de->flags = flags;
+       de->disp  = -(cd->dseglen);
+       de->val.d = value;
+       de->next  = cd->dseg;
+
+       /* insert into the chain */
+
+       cd->dseg = de;
+
+       return de->disp;
+}
+
+
+/* dseg_add_unique_double ******************************************************
+
+   Adds uniquely a double value to the data segment.
+
+*******************************************************************************/
+
+s4 dseg_add_unique_double(codegendata *cd, double value)
+{
+       s4 disp;
+
+       disp = dseg_add_double_intern(cd, value, DSEG_FLAG_UNIQUE);
+
+       return disp;
+}
+
+
+/* dseg_add_double *************************************************************
+
+   Adds a double value to the data segment. It tries to reuse
+   previously added values.
+
+*******************************************************************************/
+
+s4 dseg_add_double(codegendata *cd, double value)
+{
+       s4 disp;
+
+       /* search the data segment if the value is already stored */
+
+       disp = dseg_find_double(cd, value);
+
+       if (disp != 0)
+               return disp;
+               
+       disp = dseg_add_double_intern(cd, value, DSEG_FLAG_READONLY);
+
+       return disp;
+}
+
+
+/* dseg_add_address_intern *****************************************************
+
+   Internal function to add an address pointer to the data segment.
+
+*******************************************************************************/
+
+static s4 dseg_add_address_intern(codegendata *cd, void *value, u4 flags)
 {
-       double *dataptr;
+       dsegentry *de;
 
+       /* Increase data segment size, which is also the displacement into
+          the data segment. */
+
+#if SIZEOF_VOID_P == 8
        cd->dseglen = ALIGN(cd->dseglen + 8, 8);
-       dataptr = (double *) (cd->dsegtop - cd->dseglen);
+#else
+       cd->dseglen += 4;
+#endif
 
-       if (cd->dseglen > cd->dsegsize)
-               return dseg_adddouble_increase(cd, value);
+       /* allocate new entry */
 
-       *dataptr = value;
+       de = DNEW(dsegentry);
 
-       return -(cd->dseglen);
+       de->type  = TYPE_ADR;
+       de->flags = flags;
+       de->disp  = -(cd->dseglen);
+       de->val.a = value;
+       de->next  = cd->dseg;
+
+       /* insert into the chain */
+
+       cd->dseg = de;
+
+       return de->disp;
+}
+
+
+/* dseg_add_unique_address *****************************************************
+
+   Adds uniquely an address value to the data segment.
+
+*******************************************************************************/
+
+s4 dseg_add_unique_address(codegendata *cd, void *value)
+{
+       s4 disp;
+
+       disp = dseg_add_address_intern(cd, value, DSEG_FLAG_UNIQUE);
+
+       return disp;
+}
+
+
+/* dseg_add_address ************************************************************
+
+   Adds an address value to the data segment. It tries to reuse
+   previously added values.
+
+*******************************************************************************/
+
+s4 dseg_add_address(codegendata *cd, void *value)
+{
+       s4 disp;
+
+       /* search the data segment if the value is already stored */
+
+       disp = dseg_find_address(cd, value);
+
+       if (disp != 0)
+               return disp;
+               
+       disp = dseg_add_address_intern(cd, value, DSEG_FLAG_READONLY);
+
+       return disp;
 }
 
 
-void dseg_addtarget(codegendata *cd, basicblock *target)
+/* dseg_add_target *************************************************************
+
+   XXX
+
+*******************************************************************************/
+
+void dseg_add_target(codegendata *cd, basicblock *target)
 {
        jumpref *jr;
 
        jr = DNEW(jumpref);
 
-       jr->tablepos = dseg_addaddress(cd, NULL);
+       jr->tablepos = dseg_add_unique_address(cd, NULL);
        jr->target   = target;
        jr->next     = cd->jumpreferences;
 
@@ -196,16 +588,16 @@ void dseg_addlinenumbertablesize(codegendata *cd)
 #if SIZEOF_VOID_P == 8
        /* 4-byte ALIGNMENT PADDING */
 
-       dseg_adds4(cd, 0);
+       dseg_add_unique_s4(cd, 0);
 #endif
 
-       cd->linenumbertablesizepos  = dseg_addaddress(cd, NULL);
-       cd->linenumbertablestartpos = dseg_addaddress(cd, NULL);
+       cd->linenumbertablesizepos  = dseg_add_unique_address(cd, NULL);
+       cd->linenumbertablestartpos = dseg_add_unique_address(cd, NULL);
 
 #if SIZEOF_VOID_P == 8
        /* 4-byte ALIGNMENT PADDING */
 
-       dseg_adds4(cd, 0);
+       dseg_add_unique_s4(cd, 0);
 #endif
 }
 
@@ -221,7 +613,7 @@ void dseg_addlinenumbertablesize(codegendata *cd)
 
 *******************************************************************************/
 
-void dseg_addlinenumber(codegendata *cd, u2 linenumber, u1 *mcodeptr)
+void dseg_addlinenumber(codegendata *cd, u2 linenumber)
 {
        linenumberref *lr;
 
@@ -229,7 +621,7 @@ void dseg_addlinenumber(codegendata *cd, u2 linenumber, u1 *mcodeptr)
 
        lr->linenumber = linenumber;
        lr->tablepos   = 0;
-       lr->targetmpc  = mcodeptr - cd->mcodebase;
+       lr->targetmpc  = cd->mcodeptr - cd->mcodebase;
        lr->next       = cd->linenumberreferences;
 
        cd->linenumberreferences = lr;
@@ -248,9 +640,7 @@ void dseg_addlinenumber(codegendata *cd, u2 linenumber, u1 *mcodeptr)
 
 *******************************************************************************/
 
-void dseg_addlinenumber_inline_start(codegendata *cd, 
-                                                                        instruction *iptr, 
-                                                                        u1 *mcodeptr)
+void dseg_addlinenumber_inline_start(codegendata *cd, instruction *iptr)
 {
        linenumberref *lr;
        insinfo_inline *insinfo;
@@ -260,12 +650,12 @@ void dseg_addlinenumber_inline_start(codegendata *cd,
 
        lr->linenumber = (-2); /* marks start of inlined method */
        lr->tablepos   = 0;
-       lr->targetmpc  = (mpc = mcodeptr - cd->mcodebase);
+       lr->targetmpc  = (mpc = (u1 *) cd->mcodeptr - cd->mcodebase);
        lr->next       = cd->linenumberreferences;
 
        cd->linenumberreferences = lr;
 
-       insinfo = (insinfo_inline *) iptr->target;
+       insinfo = iptr->sx.s23.s3.inlineinfo;
 
        insinfo->startmpc = mpc; /* store for corresponding INLINE_END */
 }
@@ -291,7 +681,7 @@ void dseg_addlinenumber_inline_end(codegendata *cd, instruction *iptr)
        linenumberref *prev;
        insinfo_inline *insinfo;
 
-       insinfo = (insinfo_inline *) iptr->target;
+       insinfo = iptr->sx.s23.s3.inlineinfo;
 
        assert(insinfo);
 
@@ -328,12 +718,17 @@ void dseg_createlinenumbertable(codegendata *cd)
        linenumberref *lr;
 
        for (lr = cd->linenumberreferences; lr != NULL; lr = lr->next) {
-               lr->tablepos = dseg_addaddress(cd, NULL);
+               lr->tablepos = dseg_add_unique_address(cd, NULL);
 
                if (cd->linenumbertab == 0)
                        cd->linenumbertab = lr->tablepos;
 
-               dseg_addaddress(cd, lr->linenumber);
+#if SIZEOF_VOID_P == 8
+               /* This is for alignment and easier usage. */
+               (void) dseg_add_unique_s8(cd, lr->linenumber);
+#else
+               (void) dseg_add_unique_s4(cd, lr->linenumber);
+#endif
        }
 }
 
@@ -345,13 +740,13 @@ void dseg_createlinenumbertable(codegendata *cd)
 *******************************************************************************/
 
 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(ENABLE_INTRP)
-void dseg_adddata(codegendata *cd, u1 *mcodeptr)
+void dseg_adddata(codegendata *cd)
 {
        dataref *dr;
 
        dr = DNEW(dataref);
 
-       dr->datapos = mcodeptr - cd->mcodebase;
+       dr->datapos = cd->mcodeptr - cd->mcodebase;
        dr->next    = cd->datareferences;
 
        cd->datareferences = dr;
@@ -396,30 +791,85 @@ void dseg_display(jitdata *jd)
 {
        codeinfo    *code;
        codegendata *cd;
-       s4          *s4ptr;
-       s4           i;
-       
+       dsegentry   *de;
+       imm_union   val;
+
        /* get required compiler data */
 
        code = jd->code;
        cd   = jd->cd;
 
-       s4ptr = (s4 *) (ptrint) code->mcode;
+       if (opt_debugcolor)
+               printf("\033[34m");     /* blue */
 
        printf("  --- dump of datasegment\n");
 
-       for (i = cd->dseglen; i > 0 ; i -= 4) {
+       /* process all data segment entries */
+
+       for (de = cd->dseg; de != NULL; de = de->next) {
+#if SIZEOF_VOID_P == 8
+               printf("0x%016lx:", (ptrint) (code->entrypoint + de->disp));
+#else
+               printf("0x%08x:", (ptrint) (code->entrypoint + de->disp));
+#endif
+
+               printf("    %6x (%6d): ", de->disp, de->disp);
+
+               /* We read the values from the data segment as some values,
+                  like the line number table, have been written directly to
+                  the data segment. */
+
+               switch (de->type) {
+               case TYPE_INT:
+                       val.i = *((s4 *) (code->entrypoint + de->disp));
+                       printf("(INT) %d (0x%08x)", val.i, val.i);
+                       break;
+
+               case TYPE_LNG:
+                       val.l = *((s8 *) (code->entrypoint + de->disp));
 #if SIZEOF_VOID_P == 8
-               printf("0x%016lx:   -%6x (%6d): %8x\n",
-                          (ptrint) s4ptr, i, i, (s4) *s4ptr);
+                       printf("(LNG) %ld (0x%016lx)", val.l, val.l);
 #else
-               printf("0x%08x:   -%6x (%6d): %8x\n",
-                          (ptrint) s4ptr, i, i, (s4) *s4ptr);
+                       printf("(LNG) %lld (0x%016llx)", val.l, val.l);
 #endif
-               s4ptr++;
+                       break;
+
+               case TYPE_FLT:
+                       val.f = *((float *) (code->entrypoint + de->disp));
+                       printf("(FLT) %g (0x%08x)", val.f, val.i);
+                       break;
+
+               case TYPE_DBL:
+                       val.d = *((double *) (code->entrypoint + de->disp));
+#if SIZEOF_VOID_P == 8
+                       printf("(DBL) %g (0x%016lx)", val.d, val.l);
+#else
+                       printf("(DBL) %g (0x%016llx)", val.d, val.l);
+#endif
+                       break;
+
+               case TYPE_ADR:
+                       val.a = *((void **) (code->entrypoint + de->disp));
+#if SIZEOF_VOID_P == 8
+                       printf("(ADR) %016lx", (ptrint) val.a);
+#else
+                       printf("(ADR) %08x", (ptrint) val.a);
+#endif
+                       break;
+               }
+
+               printf("\n");
        }
 
-       printf("  --- begin of data segment: %p\n", (void *) s4ptr);
+       printf("  --- begin of data segment: ");
+#if SIZEOF_VOID_P == 8
+       printf("0x%016lx\n", (ptrint) code->entrypoint);
+#else
+       printf("0x%08x\n", (ptrint) code->entrypoint);
+#endif
+
+       if (opt_debugcolor)
+               printf("\033[m");
 }
 #endif /* !defined(NDEBUG) */