/* src/vm/jit/dseg.c - data segment handling stuff
- Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+ Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
J. Wenninger, Institut f. Computersprachen - TU Wien
Authors: Reinhard Grafl
Andreas Krall
-
- Changes: Christian Thalinger
+ Christian Thalinger
Joseph Wenninger
- Edwin Steiner
+ Edwin Steiner
- $Id: dseg.c 5253 2006-08-18 18:37:19Z tbfg $
*/
#include <assert.h>
-#include "vm/options.h"
#include "vm/types.h"
#include "mm/memory.h"
#include "vm/jit/codegen-common.h"
-
+#include "vm/jit/methodheader.h"
+#include "vmcore/options.h"
/* dseg_finish *****************************************************************
static s4 dseg_find_float(codegendata *cd, float value)
{
dsegentry *de;
+ imm_union val;
+
+ /* we compare the hex value of the float as 0.0 == -0.0 */
+
+ val.f = value;
/* 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)
+ if (de->val.i == val.i)
return de->disp;
}
static s4 dseg_find_double(codegendata *cd, double value)
{
dsegentry *de;
+ imm_union val;
+
+ /* we compare the hex value of the double as 0.0 == -0.0 */
+
+ val.d = value;
/* 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)
+ if (de->val.l == val.l)
return de->disp;
}
/* Increase data segment size, which is also the displacement into
the data segment. */
- cd->dseglen = ALIGN(cd->dseglen + 8, 8);
+ cd->dseglen = MEMORY_ALIGN(cd->dseglen + 8, 8);
/* allocate new entry */
/* Increase data segment size, which is also the displacement into
the data segment. */
- cd->dseglen = ALIGN(cd->dseglen + 8, 8);
+ cd->dseglen = MEMORY_ALIGN(cd->dseglen + 8, 8);
/* allocate new entry */
the data segment. */
#if SIZEOF_VOID_P == 8
- cd->dseglen = ALIGN(cd->dseglen + 8, 8);
+ cd->dseglen = MEMORY_ALIGN(cd->dseglen + 8, 8);
#else
cd->dseglen += 4;
#endif
IN:
cd.............current codegen data
- iptr...........the ICMD_INLINE_START instruction
+ iptr...........the ICMD_INLINE_BODY instruction
mcodeptr.......start mcodeptr of inlined body
*******************************************************************************/
cd->linenumberreferences = lr;
- insinfo = (insinfo_inline *) iptr->target;
+ insinfo = iptr->sx.s23.s3.inlineinfo;
insinfo->startmpc = mpc; /* store for corresponding INLINE_END */
}
linenumberref *prev;
insinfo_inline *insinfo;
- insinfo = (insinfo_inline *) iptr->target;
+ insinfo = iptr->sx.s23.s3.inlineinfo;
assert(insinfo);
}
+/* dseg_get_linenumber_from_pc_intern ******************************************
+
+ This function search the line number table for the line
+ corresponding to a given pc. The function recurses for inlined
+ methods.
+
+*******************************************************************************/
+
+static s4 dseg_get_linenumber_from_pc_intern(methodinfo **pm, linenumbertable_entry *lntentry, s4 lntsize, u1 *pc)
+{
+ linenumbertable_entry *lntinline; /* special entry for inlined method */
+
+ for (; lntsize > 0; lntsize--, lntentry--) {
+ /* Note: In case of inlining this may actually compare the pc
+ against a methodinfo *, yielding a non-sensical
+ result. This is no problem, however, as we ignore such
+ entries in the switch below. This way we optimize for the
+ common case (ie. a real pc in lntentry->pc). */
+
+ if (pc >= lntentry->pc) {
+ /* did we reach the current line? */
+
+ if ((s4) lntentry->line >= 0)
+ return (s4) lntentry->line;
+
+ /* we found a special inline entry (see
+ doc/inlining_stacktrace.txt for details */
+
+ switch (lntentry->line) {
+ case -1:
+ /* begin of inlined method (ie. INLINE_END
+ instruction) */
+
+ lntinline = --lntentry;/* get entry with methodinfo * */
+ lntentry--; /* skip the special entry */
+ lntsize -= 2;
+
+ /* search inside the inlined method */
+
+ if (dseg_get_linenumber_from_pc_intern(pm, lntentry, lntsize,
+ pc))
+ {
+ /* the inlined method contained the pc */
+
+ *pm = (methodinfo *) lntinline->pc;
+
+ assert(lntinline->line <= -3);
+
+ return (-3) - lntinline->line;
+ }
+
+ /* pc was not in inlined method, continue search.
+ Entries inside the inlined method will be skipped
+ because their lntentry->pc is higher than pc. */
+ break;
+
+ case -2:
+ /* end of inlined method */
+
+ return 0;
+
+ /* default: is only reached for an -3-line entry after
+ a skipped -2 entry. We can safely ignore it and
+ continue searching. */
+ }
+ }
+ }
+
+ /* not found, return 0 */
+
+ return 0;
+}
+
+
+/* dseg_get_linenumber_from_pc *************************************************
+
+ A wrapper for dseg_get_linenumber_from_pc_intern, so we don't have
+ to evaluate the method header on every call.
+
+*******************************************************************************/
+
+s4 dseg_get_linenumber_from_pc(methodinfo **pm, u1 *pv, u1 *pc)
+{
+ ptrint lntsize; /* size of line number table */
+ u1 *lntstart; /* start of line number table */
+ linenumbertable_entry *lntentry; /* points to last entry in the table */
+ s4 linenumber;
+
+#if defined(__S390__)
+ pc = (u1 *)((intptr_t)pc & 0x7FFFFFFF);
+#endif
+
+ /* get size of line number table */
+
+ lntsize = *((ptrint *) (pv + LineNumberTableSize));
+ lntstart = *((u1 **) (pv + LineNumberTableStart));
+
+ /* Subtract the size of the line number entry of the structure,
+ since the line number table start points to the pc. */
+
+ lntentry = (linenumbertable_entry *) (lntstart - SIZEOF_VOID_P);
+
+ /* get the line number */
+
+ linenumber = dseg_get_linenumber_from_pc_intern(pm, lntentry, lntsize, pc);
+
+ return linenumber;
+}
+
+
/* dseg_adddata ****************************************************************
Adds a data segment reference to the codegendata.
*******************************************************************************/
-#if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(ENABLE_INTRP)
+#if defined(__I386__) || defined(__X86_64__) || defined(__S390__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
void dseg_adddata(codegendata *cd)
{
dataref *dr;
*******************************************************************************/
-#if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(ENABLE_INTRP)
+#if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
void dseg_resolve_datareferences(jitdata *jd)
{
codeinfo *code;
{
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 */
- if (opt_colorverbose) 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("(LNG) %ld (0x%016lx)", val.l, val.l);
+#else
+ printf("(LNG) %lld (0x%016llx)", val.l, val.l);
+#endif
+ 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("0x%016lx: -%6x (%6d): %8x\n",
- (ptrint) s4ptr, i, i, (s4) *s4ptr);
+ printf("(ADR) %016lx", (ptrint) val.a);
#else
- printf("0x%08x: -%6x (%6d): %8x\n",
- (ptrint) s4ptr, i, i, (s4) *s4ptr);
+ printf("(ADR) %08x", (ptrint) val.a);
#endif
- s4ptr++;
+ break;
+ }
+
+ printf("\n");
}
- printf(" --- begin of data segment: %p\n", (void *) s4ptr);
- if (opt_colorverbose) printf("\033[m");
+ 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) */