From 99ad448b6eb0930ea46afdec5b77f8fdf6e8664e Mon Sep 17 00:00:00 2001 From: Michael Starzinger Date: Wed, 4 Nov 2009 18:32:33 +0100 Subject: [PATCH] * src/vm/jit/executionstate.c (executionstate_pop_stackframe): Moved here from replacement, was previously called md_pop_stackframe. This is needed for stack unwinding in C, so this is the right place to put it. * src/vm/jit/executionstate.h: Added prototype for above function. * src/vm/jit/replace.cpp: See above. --- src/vm/jit/executionstate.c | 113 +++++++++++++++++++++++++++++ src/vm/jit/executionstate.h | 9 +++ src/vm/jit/replace.cpp | 137 +----------------------------------- 3 files changed, 123 insertions(+), 136 deletions(-) diff --git a/src/vm/jit/executionstate.c b/src/vm/jit/executionstate.c index 2a7958dea..c37bb05f4 100644 --- a/src/vm/jit/executionstate.c +++ b/src/vm/jit/executionstate.c @@ -28,6 +28,8 @@ #include #include +#include "arch.h" +#include "md.h" #include "md-abi.h" #include "vm/descriptor.hpp" @@ -37,6 +39,117 @@ #include "vm/jit/executionstate.h" +/** + * 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. *** + * + * @param es Execution state to be modified. + * NOTE: es->code and es->pv are NOT updated. + */ +void executionstate_pop_stackframe(executionstate_t *es) +{ + int32_t reg; + int32_t i; + + // Sanity checks. + assert(es->code != NULL); + + // Calculate the size of the stackframe. + int32_t framesize = md_stacktrace_get_framesize(es->code); + + // Read the return address. + uint8_t* ra; +#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. + uintptr_t sp = (uintptr_t) es->sp; + uintptr_t basesp = sp + es->code->stackframesize * SIZE_OF_STACKSLOT; + + // 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 + basesp -= 1 * SIZE_OF_STACKSLOT; + es->ra = *((uint8_t**) basesp); +# if STACKFRAME_LEAFMETHODS_RA_REGISTER + } +# endif +#endif /* STACKFRAME_RA_TOP_OF_FRAME */ + + // Restore return address, if inside linkage area. +#if STACKFRAME_RA_LINKAGE_AREA +# if STACKFRAME_LEAFMETHODS_RA_REGISTER + if (!code_is_leafmethod(es->code)) +# endif + es->ra = *((uint8_t**) (basesp + LA_LR_OFFSET)); +#endif /* STACKFRAME_RA_LINKAGE_AREA */ + + // Restore saved int registers. + reg = INT_REG_CNT; + for (i=0; icode->savedintcount; ++i) { + while (nregdescint[--reg] != REG_SAV) + ; + basesp -= 1 * SIZE_OF_STACKSLOT; + es->intregs[reg] = *((uintptr_t*) basesp); + } + + // Restore saved flt registers. + // XXX align? + reg = FLT_REG_CNT; + for (i=0; icode->savedfltcount; ++i) { + while (nregdescfloat[--reg] != REG_SAV) + ; + basesp -= STACK_SLOTS_PER_FLOAT * SIZE_OF_STACKSLOT; + es->fltregs[reg] = *((double*) basesp); + } + +#if defined(HAS_ADDRESS_REGISTER_FILE) + // Restore saved adr registers. + reg = ADR_REG_CNT; + for (i=0; icode->savedadrcount; ++i) { + while (nregdescadr[--reg] != REG_SAV) + ; + basesp -= 1 * SIZE_OF_STACKSLOT; + es->adrregs[reg] = *((uintptr_t*) 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 (i=0; iintregs[i] = (ptrint) 0x33dead3333dead33ULL; + for (i=0; ifltregs[i]) = 0x33dead3333dead33ULL; +# if defined(HAS_ADDRESS_REGISTER_FILE) + for (i=0; iadrregs[i] = (ptrint) 0x33dead3333dead33ULL; +# endif +#endif /* !defined(NDEBUG) */ +} + + /* executionstate_sanity_check ************************************************* Perform some sanity checks for the md_executionstate_read and diff --git a/src/vm/jit/executionstate.h b/src/vm/jit/executionstate.h index 59e14ea4b..08dcc5dd8 100644 --- a/src/vm/jit/executionstate.h +++ b/src/vm/jit/executionstate.h @@ -41,6 +41,13 @@ typedef struct executionstate_t executionstate_t; #include "vm/jit/code.hpp" +/* configuration of native stack slot size ************************************/ + +#define SIZE_OF_STACKSLOT 8 +#define STACK_SLOTS_PER_FLOAT 1 +typedef uint64_t stackslot_t; + + /* executionstate_t ************************************************************ An execution-state represents the state of a thread containing all @@ -72,6 +79,8 @@ struct executionstate_t { extern "C" { #endif +void executionstate_pop_stackframe(executionstate_t *es); + #if !defined(NDEBUG) void executionstate_sanity_check(void *context); void executionstate_println(executionstate_t *es); diff --git a/src/vm/jit/replace.cpp b/src/vm/jit/replace.cpp index 67878da59..8b080b875 100644 --- a/src/vm/jit/replace.cpp +++ b/src/vm/jit/replace.cpp @@ -72,15 +72,6 @@ #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 ****************************************************************/ #if !defined(NDEBUG) @@ -1461,132 +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 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 STACKFRAME_RA_LINKAGE_AREA -# if STACKFRAME_LEAFMETHODS_RA_REGISTER - if (!code_is_leafmethod(es->code)) -# endif - es->ra = *((uint8_t**) ((intptr_t) basesp + LA_LR_OFFSET)); -#endif /* STACKFRAME_RA_LINKAGE_AREA */ - - /* restore saved int registers */ - - reg = INT_REG_CNT; - for (i=0; icode->savedintcount; ++i) { - while (nregdescint[--reg] != REG_SAV) - ; - basesp -= 1; - es->intregs[reg] = *((uintptr_t*) basesp); - } - - /* restore saved flt registers */ - - /* XXX align? */ - reg = FLT_REG_CNT; - for (i=0; icode->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; icode->savedadrcount; ++i) { - while (nregdescadr[--reg] != REG_SAV) - ; - basesp -= 1; - es->adrregs[reg] = *((uintptr_t*) 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; iintregs[i] = (ptrint) 0x33dead3333dead33ULL; - for (i=0; ifltregs[i]) = 0x33dead3333dead33ULL; -# if defined(HAS_ADDRESS_REGISTER_FILE) - for (i=0; iadrregs[i] = (ptrint) 0x33dead3333dead33ULL; -# endif -#endif /* !defined(NDEBUG) */ -} - - /* md_push_stackframe ********************************************************** Save the given return address, build the new stackframe, @@ -1767,7 +1632,7 @@ u1* replace_pop_activation_record(executionstate_t *es, /* pop the stackframe */ - md_pop_stackframe(es); + executionstate_pop_stackframe(es); ra = es->pc; -- 2.25.1