/* src/vm/jit/replace.cpp - on-stack replacement of methods
- Copyright (C) 1996-2005, 2006, 2007, 2008
+ Copyright (C) 1996-2005, 2006, 2007, 2008, 2009
CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#endif
#include "mm/dumpmemory.hpp"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "threads/thread.hpp"
-#include "toolbox/logging.h"
+#include "toolbox/logging.hpp"
#include "vm/classcache.hpp"
#include "vm/globals.hpp"
/*** architecture-dependent configuration *************************************/
/* first unset the macros (default) */
-#undef REPLACE_RA_BETWEEN_FRAMES
-#undef REPLACE_RA_TOP_OF_FRAME
#undef REPLACE_RA_LINKAGE_AREA
-#undef REPLACE_LEAFMETHODS_RA_REGISTER
-
-/* i386, x86_64 and m68k */
-#if defined(__I386__) || defined(__X86_64__) || defined(__M68K__)
-#define REPLACE_RA_BETWEEN_FRAMES
-/* alpha */
-#elif defined(__ALPHA__)
-#define REPLACE_RA_TOP_OF_FRAME
-#define REPLACE_LEAFMETHODS_RA_REGISTER
+
/* powerpc */
-#elif defined(__POWERPC__)
-#define REPLACE_RA_LINKAGE_AREA
-#define REPLACE_LEAFMETHODS_RA_REGISTER
-/* s390 */
-#elif defined(__S390__)
-#define REPLACE_RA_TOP_OF_FRAME
+#if defined(__POWERPC__)
+# define REPLACE_RA_LINKAGE_AREA
#endif
code->regalloc = regalloc;
code->regalloccount = alloccount;
code->globalcount = 0;
- code->savedintcount = INT_SAV_CNT - rd->savintreguse;
- code->savedfltcount = FLT_SAV_CNT - rd->savfltreguse;
-#if defined(HAS_ADDRESS_REGISTER_FILE)
- code->savedadrcount = ADR_SAV_CNT - rd->savadrreguse;
-#endif
code->memuse = rd->memuse;
- code->stackframesize = jd->cd->stackframesize;
REPLACE_COUNT_DIST(stat_dist_method_rplpoints, count);
REPLACE_COUNT_INC(stat_regallocs, alloccount);
void md_pop_stackframe(executionstate_t *es)
{
u1 *ra;
- s4 ra_align_off;
+ s4 framesize;
s4 reg;
s4 i;
stackslot_t *basesp;
assert(es->code);
- /* alignment offset of RA */
+ /* calculate the size of the stackframe */
- ra_align_off = 0;
-#if defined(REPLACE_RA_BETWEEN_FRAMES)
- if (es->code->stackframesize)
- ra_align_off = SIZE_OF_STACKSLOT - SIZEOF_VOID_P;
-#endif
+ framesize = md_stacktrace_get_framesize(es->code);
/* read the return address */
-#if defined(REPLACE_LEAFMETHODS_RA_REGISTER)
+#if STACKFRAME_LEAFMETHODS_RA_REGISTER
if (code_is_leafmethod(es->code))
ra = es->ra;
else
#endif
- ra = (u1*) md_stacktrace_get_returnaddress(es->sp,
- SIZE_OF_STACKSLOT * es->code->stackframesize + ra_align_off);
+ ra = (u1*) md_stacktrace_get_returnaddress(es->sp, framesize);
/* calculate the base of the stack frame */
/* restore return address, if part of frame */
-#if defined(REPLACE_RA_TOP_OF_FRAME)
-#if defined(REPLACE_LEAFMETHODS_RA_REGISTER)
+#if STACKFRAME_RA_TOP_OF_FRAME
+# if STACKFRAME_LEAFMETHODS_RA_REGISTER
if (!code_is_leafmethod(es->code))
-#endif
+# endif
es->ra = (u1*) (ptrint) *--basesp;
-#endif /* REPLACE_RA_TOP_OF_FRAME */
+#endif /* STACKFRAME_RA_TOP_OF_FRAME */
#if defined(REPLACE_RA_LINKAGE_AREA)
-#if defined(REPLACE_LEAFMETHODS_RA_REGISTER)
+# if STACKFRAME_LEAFMETHODS_RA_REGISTER
if (!code_is_leafmethod(es->code))
-#endif
+# endif
es->ra = (u1*) (ptrint) basesp[LA_LR_OFFSET / sizeof(stackslot_t)];
#endif /* REPLACE_RA_LINKAGE_AREA */
/* adjust the stackpointer */
- es->sp += SIZE_OF_STACKSLOT * es->code->stackframesize;
-
-#if defined(REPLACE_RA_BETWEEN_FRAMES)
- es->sp += ra_align_off + SIZEOF_VOID_P; /* skip return address */
+ es->sp += framesize;
+#if STACKFRMAE_RA_BETWEEN_FRAMES
+ es->sp += SIZEOF_VOID_P; /* skip return address */
#endif
/* set the program counter to the return address */
/* write the return address */
-#if defined(REPLACE_RA_BETWEEN_FRAMES)
+#if STACKFRMAE_RA_BETWEEN_FRAMES
es->sp -= SIZEOF_VOID_P;
*((void **)es->sp) = (void *) ra;
if (calleecode->stackframesize)
es->sp -= (SIZE_OF_STACKSLOT - SIZEOF_VOID_P);
-#endif /* REPLACE_RA_BETWEEN_FRAMES */
+#endif /* STACKFRAME_RA_BETWEEN_FRAMES */
es->ra = (u1*) (ptrint) ra;
/* save the return address register */
-#if defined(REPLACE_RA_TOP_OF_FRAME)
-#if defined(REPLACE_LEAFMETHODS_RA_REGISTER)
+#if STACKFRAME_RA_TOP_OF_FRAME
+# if STACKFRAME_LEAFMETHODS_RA_REGISTER
if (!code_is_leafmethod(calleecode))
-#endif
+# endif
*--basesp = (ptrint) ra;
-#endif /* REPLACE_RA_TOP_OF_FRAME */
+#endif /* STACKFRAME_RA_TOP_OF_FRAME */
#if defined(REPLACE_RA_LINKAGE_AREA)
-#if defined(REPLACE_LEAFMETHODS_RA_REGISTER)
+# if STACKFRAME_LEAFMETHODS_RA_REGISTER
if (!code_is_leafmethod(calleecode))
-#endif
+# endif
basesp[LA_LR_OFFSET / sizeof(stackslot_t)] = (ptrint) ra;
#endif /* REPLACE_RA_LINKAGE_AREA */
/* restore sp, pv, pc and codeinfo of the parent method */
- /* XXX michi: use this instead:
- es->sp = sfi->sp + code->stackframesize; */
- es->sp = (uint8_t*) (((uintptr_t) sfi->sp) + (*(s4 *) (((uintptr_t) sfi->pv) + FrameSize)));
-#if defined(REPLACE_RA_BETWEEN_FRAMES)
- es->sp += SIZE_OF_STACKSLOT; /* skip return address */
+ es->sp = (uint8_t*) (((uintptr_t) sfi->sp) + md_stacktrace_get_framesize(code));
+#if STACKFRMAE_RA_BETWEEN_FRAMES
+ es->sp += SIZEOF_VOID_P; /* skip return address */
#endif
es->pv = (uint8_t*) md_codegen_get_pv_from_pc(sfi->ra);
es->pc = (uint8_t*) (((uintptr_t) ((sfi->xpc) ? sfi->xpc : sfi->ra)) - 1);
/* skip sp for the native stub */
- es->sp -= (*(s4 *) (((uintptr_t) frame->sfi->pv) + FrameSize));
-#if defined(REPLACE_RA_BETWEEN_FRAMES)
- es->sp -= SIZE_OF_STACKSLOT; /* skip return address */
+ es->sp -= md_stacktrace_get_framesize(frame->sfi->code);
+#if STACKFRMAE_RA_BETWEEN_FRAMES
+ es->sp -= SIZEOF_VOID_P; /* skip return address */
#endif
/* assert that the native frame has not moved */
}
-/* replace_me_wrapper **********************************************************
+/* replace_handler *************************************************************
This function is called by the signal handler. It determines if there
is an active replacement point pending at the given PC and returns
IN:
pc...............the program counter that triggered the replacement.
- context..........the context (machine state) to which the
+ es...............the execution state (machine state) to which the
replacement should be applied.
OUT:
- context..........the context after replacement finished.
+ es...............the execution state after replacement finished.
RETURN VALUE:
true.............replacement done, everything went ok
- false............no replacement done, context unchanged
+ false............no replacement done, execution state unchanged
*******************************************************************************/
-bool replace_me_wrapper(u1 *pc, void *context)
+bool replace_handler(u1 *pc, executionstate_t *es)
{
codeinfo *code;
rplpoint *rp;
- executionstate_t es;
#if defined(ENABLE_RT_TIMING)
struct timespec time_start, time_end;
#endif
DOLOG( printf("valid replacement point\n"); );
-#if !defined(NDEBUG)
- executionstate_sanity_check(context);
-#endif
-
/* set codeinfo pointer in execution state */
- es.code = code;
-
- /* read execution state from current context */
-
- md_executionstate_read(&es, context);
-
- DOLOG( printf("REPLACEMENT READ: ");
- executionstate_println(&es); );
+ es->code = code;
/* do the actual replacement */
RT_TIMING_GET_TIME(time_start);
#endif
- replace_me(rp, &es);
+ replace_me(rp, es);
#if defined(ENABLE_RT_TIMING)
RT_TIMING_GET_TIME(time_end);
RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_REPLACE);
#endif
- /* write execution state to current context */
-
- md_executionstate_write(&es, context);
-
- DOLOG( printf("REPLACEMENT WRITE: ");
- executionstate_println(&es); );
-
/* new code is entered after returning */
DOLOG( printf("JUMPING IN!\n"); fflush(stdout); );