* src/vm/jit/x86_64/asmpart.S (asm_abstractmethoderror): Keep stack aligned.
[cacao.git] / src / vm / jit / replace.cpp
index b0644f1317f091dcfdba349001fd68507eb2ac39..8b080b8753bc3680a072e088f41f9c5335d2634b 100644 (file)
@@ -1,6 +1,6 @@
 /* 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.
@@ -38,7 +38,7 @@
 #endif
 
 #include "mm/dumpmemory.hpp"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
 
 #include "threads/thread.hpp"
 
 #include <vmlog_cacao.h>
 #endif
 
-/*** 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
-#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 ****************************************************************/
 
@@ -728,13 +695,7 @@ bool replace_create_replacement_points(jitdata *jd)
        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);
@@ -1491,136 +1452,6 @@ static void replace_write_executionstate(rplpoint *rp,
 }
 
 
-/* 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 ra_align_off;
-       s4 reg;
-       s4 i;
-       stackslot_t *basesp;
-       stackslot_t *sp;
-
-       assert(es->code);
-
-       /* alignment offset of RA */
-
-       ra_align_off = 0;
-#if defined(REPLACE_RA_BETWEEN_FRAMES)
-    if (es->code->stackframesize)
-               ra_align_off = SIZE_OF_STACKSLOT - SIZEOF_VOID_P;
-#endif
-
-       /* read the return address */
-
-#if defined(REPLACE_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);
-
-       /* 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 defined(REPLACE_RA_TOP_OF_FRAME)
-#if defined(REPLACE_LEAFMETHODS_RA_REGISTER)
-       if (!code_is_leafmethod(es->code))
-#endif
-               es->ra = (u1*) (ptrint) *--basesp;
-#endif /* REPLACE_RA_TOP_OF_FRAME */
-
-#if defined(REPLACE_RA_LINKAGE_AREA)
-#if defined(REPLACE_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 += SIZE_OF_STACKSLOT * es->code->stackframesize;
-
-#if defined(REPLACE_RA_BETWEEN_FRAMES)
-       es->sp += ra_align_off + 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,
@@ -1652,12 +1483,12 @@ void md_push_stackframe(executionstate_t *es, codeinfo *calleecode, u1 *ra)
 
        /* 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;
 
@@ -1692,19 +1523,19 @@ void md_push_stackframe(executionstate_t *es, codeinfo *calleecode, u1 *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_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 */
+# endif
+               *((uint8_t**) ((intptr_t) basesp + LA_LR_OFFSET)) = ra;
+#endif /* STACKFRAME_RA_LINKAGE_AREA */
 
        /* save int registers */
 
@@ -1712,7 +1543,8 @@ void md_push_stackframe(executionstate_t *es, codeinfo *calleecode, u1 *ra)
        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
@@ -1728,7 +1560,7 @@ void md_push_stackframe(executionstate_t *es, codeinfo *calleecode, u1 *ra)
                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
@@ -1743,7 +1575,8 @@ void md_push_stackframe(executionstate_t *es, codeinfo *calleecode, u1 *ra)
        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
@@ -1794,12 +1627,12 @@ u1* replace_pop_activation_record(executionstate_t *es,
        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;
 
@@ -2122,7 +1955,7 @@ void replace_push_activation_record(executionstate_t *es,
        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 */
@@ -2371,11 +2204,9 @@ static void replace_pop_native_frame(executionstate_t *es,
 
        /* 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);
@@ -2422,9 +2253,9 @@ static void replace_push_native_frame(executionstate_t *es, sourcestate_t *ss)
 
        /* 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 */
@@ -2963,7 +2794,7 @@ static void replace_me(rplpoint *rp, executionstate_t *es)
 }
 
 
-/* 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
@@ -2973,23 +2804,22 @@ static void replace_me(rplpoint *rp, executionstate_t *es)
 
    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
@@ -3010,20 +2840,9 @@ bool replace_me_wrapper(u1 *pc, void *context)
 
                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 */
 
@@ -3031,20 +2850,13 @@ bool replace_me_wrapper(u1 *pc, void *context)
                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); );