X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fvm%2Fjit%2Fdseg.c;h=2c08e8b66d621ad215dfccb3b5fbaece7860d10d;hb=d00bf847452f94e7acd4e907287630dad7df0503;hp=cfe121ef282eb08534ce011f0db82d2d90e7a220;hpb=3ae649d7d8c0f0c0301b33e9bbbc76361c7e4af5;p=cacao.git diff --git a/src/vm/jit/dseg.c b/src/vm/jit/dseg.c index cfe121ef2..2c08e8b66 100644 --- a/src/vm/jit/dseg.c +++ b/src/vm/jit/dseg.c @@ -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 $ */ @@ -40,144 +40,536 @@ #include +#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) */