/* 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.
#include <vmlog_cacao.h>
#endif
-/*** architecture-dependent configuration *************************************/
-
-/* first unset the macros (default) */
-#undef REPLACE_RA_LINKAGE_AREA
-
-/* powerpc */
-#if defined(__POWERPC__)
-# define REPLACE_RA_LINKAGE_AREA
-#endif
-
-
-/*** configuration of native stack slot size **********************************/
-
-/* XXX this should be in md-abi.h files, probably */
-
-#define SIZE_OF_STACKSLOT 8
-#define STACK_SLOTS_PER_FLOAT 1
-typedef u8 stackslot_t;
-
/*** debugging ****************************************************************/
}
-/* md_pop_stackframe ***********************************************************
-
- Restore callee-saved registers (including the RA register),
- set the stack pointer to the next stackframe,
- set the PC to the return address of the popped frame.
-
- *** This function imitates the effects of the method epilog ***
- *** and returning from the method call. ***
-
- IN:
- es...............execution state
-
- OUT:
- *es..............the execution state after popping the stack frame
- NOTE: es->code and es->pv are NOT updated.
-
-*******************************************************************************/
-
-void md_pop_stackframe(executionstate_t *es)
-{
- u1 *ra;
- s4 framesize;
- s4 reg;
- s4 i;
- stackslot_t *basesp;
- stackslot_t *sp;
-
- assert(es->code);
-
- /* calculate the size of the stackframe */
-
- framesize = md_stacktrace_get_framesize(es->code);
-
- /* read the return address */
-
-#if STACKFRAME_LEAFMETHODS_RA_REGISTER
- if (code_is_leafmethod(es->code))
- ra = es->ra;
- else
-#endif
- ra = (u1*) md_stacktrace_get_returnaddress(es->sp, framesize);
-
- /* calculate the base of the stack frame */
-
- sp = (stackslot_t *) es->sp;
- basesp = sp + es->code->stackframesize;
-
- /* restore return address, if part of frame */
-
-#if STACKFRAME_RA_TOP_OF_FRAME
-# if STACKFRAME_LEAFMETHODS_RA_REGISTER
- if (!code_is_leafmethod(es->code))
-# endif
- es->ra = (u1*) (ptrint) *--basesp;
-#endif /* STACKFRAME_RA_TOP_OF_FRAME */
-
-#if defined(REPLACE_RA_LINKAGE_AREA)
-# if STACKFRAME_LEAFMETHODS_RA_REGISTER
- if (!code_is_leafmethod(es->code))
-# endif
- es->ra = (u1*) (ptrint) basesp[LA_LR_OFFSET / sizeof(stackslot_t)];
-#endif /* REPLACE_RA_LINKAGE_AREA */
-
- /* restore saved int registers */
-
- reg = INT_REG_CNT;
- for (i=0; i<es->code->savedintcount; ++i) {
- while (nregdescint[--reg] != REG_SAV)
- ;
- es->intregs[reg] = *--basesp;
- }
-
- /* restore saved flt registers */
-
- /* XXX align? */
- reg = FLT_REG_CNT;
- for (i=0; i<es->code->savedfltcount; ++i) {
- while (nregdescfloat[--reg] != REG_SAV)
- ;
- basesp -= STACK_SLOTS_PER_FLOAT;
- es->fltregs[reg] = *(double*)basesp;
- }
-
-#if defined(HAS_ADDRESS_REGISTER_FILE)
- /* restore saved adr registers */
-
- reg = ADR_REG_CNT;
- for (i=0; i<es->code->savedadrcount; ++i) {
- while (nregdescadr[--reg] != REG_SAV)
- ;
- es->adrregs[reg] = *--basesp;
- }
-#endif
-
- /* adjust the stackpointer */
-
- 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 */
-
- es->pc = ra;
-
- /* in debugging mode clobber non-saved registers */
-
-#if !defined(NDEBUG)
- /* for debugging */
- for (i=0; i<INT_REG_CNT; ++i)
- if (nregdescint[i] != REG_SAV)
- es->intregs[i] = (ptrint) 0x33dead3333dead33ULL;
- for (i=0; i<FLT_REG_CNT; ++i)
- if (nregdescfloat[i] != REG_SAV)
- *(u8*)&(es->fltregs[i]) = 0x33dead3333dead33ULL;
-# if defined(HAS_ADDRESS_REGISTER_FILE)
- for (i=0; i<ADR_REG_CNT; ++i)
- if (nregdescadr[i] != REG_SAV)
- es->adrregs[i] = (ptrint) 0x33dead3333dead33ULL;
-# endif
-#endif /* !defined(NDEBUG) */
-}
-
-
/* md_push_stackframe **********************************************************
Save the given return address, build the new stackframe,
*--basesp = (ptrint) ra;
#endif /* STACKFRAME_RA_TOP_OF_FRAME */
-#if defined(REPLACE_RA_LINKAGE_AREA)
+#if STACKFRAME_RA_LINKAGE_AREA
# if STACKFRAME_LEAFMETHODS_RA_REGISTER
if (!code_is_leafmethod(calleecode))
# endif
- basesp[LA_LR_OFFSET / sizeof(stackslot_t)] = (ptrint) ra;
-#endif /* REPLACE_RA_LINKAGE_AREA */
+ *((uint8_t**) ((intptr_t) basesp + LA_LR_OFFSET)) = ra;
+#endif /* STACKFRAME_RA_LINKAGE_AREA */
/* save int registers */
for (i=0; i<calleecode->savedintcount; ++i) {
while (nregdescint[--reg] != REG_SAV)
;
- *--basesp = es->intregs[reg];
+ basesp -= 1;
+ *((uintptr_t*) basesp) = es->intregs[reg];
/* XXX may not clobber saved regs used by native code! */
#if !defined(NDEBUG) && 0
while (nregdescfloat[--reg] != REG_SAV)
;
basesp -= STACK_SLOTS_PER_FLOAT;
- *(double*)basesp = es->fltregs[reg];
+ *((double*) basesp) = es->fltregs[reg];
/* XXX may not clobber saved regs used by native code! */
#if !defined(NDEBUG) && 0
for (i=0; i<calleecode->savedadrcount; ++i) {
while (nregdescadr[--reg] != REG_SAV)
;
- *--basesp = es->adrregs[reg];
+ basesp -= 1;
+ *((uintptr_t*) basesp) = es->adrregs[reg];
/* XXX may not clobber saved regs used by native code! */
#if !defined(NDEBUG) && 0
frame->syncslotcount = count;
frame->syncslots = (replace_val_t*) DumpMemory::allocate(sizeof(replace_val_t) * count);
for (i=0; i<count; ++i) {
- frame->syncslots[i].p = sp[es->code->memuse + i]; /* XXX md_ function */
+ frame->syncslots[i].p = *((intptr_t*) (sp + es->code->memuse + i)); /* XXX md_ function */
}
/* pop the stackframe */
- md_pop_stackframe(es);
+ executionstate_pop_stackframe(es);
ra = es->pc;
count = code_get_sync_slot_count(calleecode);
assert(count == calleeframe->syncslotcount);
for (i=0; i<count; ++i) {
- sp[calleecode->memuse + i] = calleeframe->syncslots[i].p;
+ *((intptr_t*) (sp + calleecode->memuse + i)) = calleeframe->syncslots[i].p;
}
/* redirect future invocations */
}
-/* 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); );