X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fvm%2Fjit%2Freplace.c;h=c0b170231bfd8be55c1e4c2b871644bebbf7fc5f;hb=caf4bfb972a703ceeaa4bdf5afb820bce15fd7e6;hp=4a3bfa4715f1c87b57f63b2fa138498f71b78563;hpb=c330479c609cc9a9fb98cc64ed07bcbf6908744e;p=cacao.git diff --git a/src/vm/jit/replace.c b/src/vm/jit/replace.c index 4a3bfa471..c0b170231 100644 --- a/src/vm/jit/replace.c +++ b/src/vm/jit/replace.c @@ -22,14 +22,13 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - $Id$ - */ #include "config.h" #include "vm/types.h" #include +#include #include #include "arch.h" @@ -89,6 +88,10 @@ #define REPLACE_RA_LINKAGE_AREA #define REPLACE_LEAFMETHODS_RA_REGISTER #define REPLACE_REG_RA REG_ITMP3 /* the execution state has the LR in itmp3 */ +/* s390 */ +#elif defined(__S390__) +#define REPLACE_RA_TOP_OF_FRAME +#define REPLACE_REG_RA REG_ITMP3 #endif @@ -111,7 +114,7 @@ typedef u8 stackslot_t; #if !defined(NDEBUG) static void java_value_print(s4 type, replace_val_t value); -static void replace_stackframeinfo_println(stackframeinfo *sfi); +static void replace_stackframeinfo_println(stackframeinfo_t *sfi); #endif #if !defined(NDEBUG) @@ -426,11 +429,6 @@ bool replace_create_replacement_points(jitdata *jd) m = code->m; - /* set codeinfo flags */ - - if (jd->isleafmethod) - CODE_SETFLAG_LEAFMETHOD(code); - /* in instance methods, we may need a rplpoint at the method entry */ #if defined(REPLACE_PATCH_DYNAMIC_CALL) @@ -803,7 +801,6 @@ void replace_activate_replacement_points(codeinfo *code, bool mappable) rplpoint *rp; s4 i; s4 count; - s4 index; u1 *savedmcode; assert(code->savedmcode == NULL); @@ -811,15 +808,12 @@ void replace_activate_replacement_points(codeinfo *code, bool mappable) /* count trappable replacement points */ count = 0; - index = 0; i = code->rplpointcount; rp = code->rplpoints; for (; i--; rp++) { if (rp->flags & RPLPOINT_FLAG_NOTRAP) continue; - index++; - if (mappable && (rp->type == RPLPOINT_TYPE_RETURN)) continue; @@ -843,8 +837,6 @@ void replace_activate_replacement_points(codeinfo *code, bool mappable) if (rp->flags & RPLPOINT_FLAG_NOTRAP) continue; - index--; - if (mappable && (rp->type == RPLPOINT_TYPE_RETURN)) continue; @@ -853,9 +845,20 @@ void replace_activate_replacement_points(codeinfo *code, bool mappable) savedmcode -= REPLACEMENT_PATCH_SIZE; -#if (defined(__I386__) || defined(__X86_64__) || defined(__ALPHA__) || defined(__POWERPC__) || defined(__MIPS__)) && defined(ENABLE_JIT) - md_patch_replacement_point(code, index, rp, savedmcode); +#if defined(ENABLE_JIT) +# if defined(ENABLE_DISASSEMBLER) + DOLOG( printf("\tinstruction before: "); + disassinstr(rp->pc); fflush(stdout); ); +# endif + + md_patch_replacement_point(rp->pc, savedmcode, false); + +# if defined(ENABLE_DISASSEMBLER) + DOLOG( printf("\tinstruction after : "); + disassinstr(rp->pc); fflush(stdout); ); +# endif #endif + rp->flags |= RPLPOINT_FLAG_ACTIVE; } @@ -915,8 +918,18 @@ void replace_deactivate_replacement_points(codeinfo *code) DOLOG( printf("deactivate replacement point:\n"); replace_replacement_point_println(rp, 1); fflush(stdout); ); -#if (defined(__I386__) || defined(__X86_64__) || defined(__ALPHA__) || defined(__POWERPC__) || defined(__MIPS__)) && defined(ENABLE_JIT) - md_patch_replacement_point(code, -1, rp, savedmcode); +#if defined(ENABLE_JIT) +# if defined(ENABLE_DISASSEMBLER) + DOLOG( printf("\tinstruction before: "); + disassinstr(rp->pc); fflush(stdout); ); +# endif + + md_patch_replacement_point(rp->pc, savedmcode, true); + +# if defined(ENABLE_DISASSEMBLER) + DOLOG( printf("\tinstruction before: "); + disassinstr(rp->pc); fflush(stdout); ); +# endif #endif rp->flags &= ~RPLPOINT_FLAG_ACTIVE; @@ -944,7 +957,6 @@ void replace_deactivate_replacement_points(codeinfo *code) IN: es...............execution state - sp...............stack pointer of the execution state (XXX eliminate?) ra...............allocation javaval..........where to put the value @@ -954,7 +966,6 @@ void replace_deactivate_replacement_points(codeinfo *code) *******************************************************************************/ static void replace_read_value(executionstate_t *es, - stackslot_t *sp, rplalloc *ra, replace_val_t *javaval) { @@ -962,11 +973,11 @@ static void replace_read_value(executionstate_t *es, /* XXX HAS_4BYTE_STACKSLOT may not be the right discriminant here */ #ifdef HAS_4BYTE_STACKSLOT if (IS_2_WORD_TYPE(ra->type)) { - javaval->l = *(u8*)(sp + ra->regoff); + javaval->l = *(u8*)(es->sp + ra->regoff); } else { #endif - javaval->p = sp[ra->regoff]; + javaval->p = *(ptrint*)(es->sp + ra->regoff); #ifdef HAS_4BYTE_STACKSLOT } #endif @@ -1004,14 +1015,12 @@ static void replace_read_value(executionstate_t *es, IN: es...............execution state - sp...............stack pointer of the execution state (XXX eliminate?) ra...............allocation *javaval.........the value *******************************************************************************/ static void replace_write_value(executionstate_t *es, - stackslot_t *sp, rplalloc *ra, replace_val_t *javaval) { @@ -1019,11 +1028,11 @@ static void replace_write_value(executionstate_t *es, /* XXX HAS_4BYTE_STACKSLOT may not be the right discriminant here */ #ifdef HAS_4BYTE_STACKSLOT if (IS_2_WORD_TYPE(ra->type)) { - *(u8*)(sp + ra->regoff) = javaval->l; + *(u8*)(es->sp + ra->regoff) = javaval->l; } else { #endif - sp[ra->regoff] = javaval->p; + *(ptrint*)(es->sp + ra->regoff) = javaval->p; #ifdef HAS_4BYTE_STACKSLOT } #endif @@ -1054,15 +1063,15 @@ static void replace_write_value(executionstate_t *es, } -/* replace_read_executionstate ************************************************* +/* replace_new_sourceframe ***************************************************** - Read the given executions state and translate it to a source frame. + Allocate a new source frame and insert it at the front of the frame list. IN: ss...............the source state OUT: - ss->frames.......set to new frame + ss->frames.......set to new frame (the new head of the frame list). RETURN VALUE: returns the new frame @@ -1085,15 +1094,20 @@ static sourceframe_t *replace_new_sourceframe(sourcestate_t *ss) /* replace_read_executionstate ************************************************* - Read the given executions state and translate it to a source frame. + Read a source frame from the given executions state. + The new source frame is pushed to the front of the frame list of the + source state. IN: rp...............replacement point at which `es` was taken es...............execution state - ss...............where to put the source state + ss...............the source state to add the source frame to + topframe.........true, if the first (top-most) source frame on the + stack is to be read OUT: - *ss..............the source state derived from the execution state + *ss..............the source state with the newly created source frame + added *******************************************************************************/ @@ -1139,7 +1153,7 @@ static void replace_read_executionstate(rplpoint *rp, /* calculate base stack pointer */ - basesp = sp + code_get_stack_frame_size(code); + basesp = sp + code->stackframesize; /* create the source frame */ @@ -1186,7 +1200,7 @@ static void replace_read_executionstate(rplpoint *rp, if (ra->type == TYPE_RET) frame->javalocals[i].i = ra->regoff; else - replace_read_value(es, sp, ra, frame->javalocals + i); + replace_read_value(es, ra, frame->javalocals + i); ra++; count--; } @@ -1211,12 +1225,12 @@ static void replace_read_executionstate(rplpoint *rp, instra.regoff = md->params[0].regoff; if (md->params[0].inmemory) { instra.flags = INMEMORY; - instra.regoff += (1 + code->stackframesize); + instra.regoff += (1 + code->stackframesize) * SIZE_OF_STACKSLOT; } else { instra.flags = 0; } - replace_read_value(es, sp, &instra, &(frame->instance)); + replace_read_value(es, &instra, &(frame->instance)); #endif } #endif /* defined(REPLACE_PATCH_DYNAMIC_CALL) */ @@ -1288,7 +1302,7 @@ static void replace_read_executionstate(rplpoint *rp, calleeframe->syncslotcount = 1; calleeframe->syncslots = DMNEW(replace_val_t, 1); - replace_read_value(es,sp,ra,calleeframe->syncslots); + replace_read_value(es,ra,calleeframe->syncslots); } frame->javastackdepth--; @@ -1306,7 +1320,7 @@ static void replace_read_executionstate(rplpoint *rp, if (ra->type == TYPE_RET) frame->javastack[i].i = ra->regoff; else - replace_read_value(es,sp,ra,frame->javastack + i); + replace_read_value(es,ra,frame->javastack + i); frame->javastacktype[i] = ra->type; i++; } @@ -1316,13 +1330,16 @@ static void replace_read_executionstate(rplpoint *rp, /* replace_write_executionstate ************************************************ - Translate the given source state into an execution state. - + Pop a source frame from the front of the frame list of the given source state + and write its values into the execution state. + IN: rp...............replacement point for which execution state should be - creates - es...............where to put the execution state + created + es...............the execution state to modify ss...............the given source state + topframe.........true, if this is the last (top-most) source frame to be + translated OUT: *es..............the execution state derived from the source state @@ -1358,7 +1375,7 @@ static void replace_write_executionstate(rplpoint *rp, sp = (stackslot_t *) es->sp; - basesp = sp + code_get_stack_frame_size(code); + basesp = sp + code->stackframesize; /* in some cases the top stack slot is passed in REG_ITMP1 */ @@ -1379,7 +1396,7 @@ static void replace_write_executionstate(rplpoint *rp, /* XXX assert that it matches this rplpoint */ } else - replace_write_value(es, sp, ra, frame->javalocals + i); + replace_write_value(es, ra, frame->javalocals + i); count--; ra++; } @@ -1436,7 +1453,7 @@ static void replace_write_executionstate(rplpoint *rp, assert(frame->down->syncslotcount == 1); /* XXX need to understand more cases */ assert(frame->down->syncslots != NULL); - replace_write_value(es,sp,ra,frame->down->syncslots); + replace_write_value(es,ra,frame->down->syncslots); } continue; } @@ -1455,7 +1472,7 @@ static void replace_write_executionstate(rplpoint *rp, /* XXX assert that it matches this rplpoint */ } else { - replace_write_value(es,sp,ra,frame->javastack + i); + replace_write_value(es,ra,frame->javastack + i); } i++; } @@ -1501,14 +1518,14 @@ u1* replace_pop_activation_record(executionstate_t *es, /* read the return address */ #if defined(REPLACE_LEAFMETHODS_RA_REGISTER) - if (CODE_IS_LEAFMETHOD(es->code)) + if (code_is_leafmethod(es->code)) ra = (u1*) (ptrint) es->intregs[REPLACE_REG_RA]; else #endif ra = md_stacktrace_get_returnaddress(es->sp, SIZE_OF_STACKSLOT * es->code->stackframesize); - DOLOG( printf("return address: %p\n", (void*)ra); ); + DOLOG( printf("RA = %p\n", (void*)ra); ); assert(ra); @@ -1532,14 +1549,14 @@ u1* replace_pop_activation_record(executionstate_t *es, #if defined(REPLACE_RA_TOP_OF_FRAME) #if defined(REPLACE_LEAFMETHODS_RA_REGISTER) - if (!CODE_IS_LEAFMETHOD(es->code)) + if (!code_is_leafmethod(es->code)) #endif es->intregs[REPLACE_REG_RA] = *--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)) + if (!code_is_leafmethod(es->code)) #endif es->intregs[REPLACE_REG_RA] = basesp[LA_LR_OFFSET / sizeof(stackslot_t)]; #endif /* REPLACE_RA_LINKAGE_AREA */ @@ -1591,14 +1608,9 @@ u1* replace_pop_activation_record(executionstate_t *es, /* find the new codeinfo */ pv = md_codegen_get_pv_from_pc(ra); - DOLOG( printf("PV = %p\n", (void*) pv); ); - if (pv == NULL) /* XXX can this really happen? */ - return NULL; - - code = *(codeinfo **)(pv + CodeinfoPointer); - + code = code_get_codeinfo_for_pv(pv); DOLOG( printf("CODE = %p\n", (void*) code); ); /* return NULL if we reached native code */ @@ -1656,8 +1668,8 @@ static void replace_patch_method_pointer(methodptr *mpp, (void*) *mpp, (void*)entrypoint); ); #if !defined(NDEBUG) - oldcode = *(codeinfo **)((u1*)(*mpp) + CodeinfoPointer); - newcode = *(codeinfo **)((u1*)(entrypoint) + CodeinfoPointer); + oldcode = code_get_codeinfo_for_pv(*mpp); + newcode = code_get_codeinfo_for_pv(entrypoint); DOLOG_SHORT( printf("\tpatch %s %p ", kind, (void*) oldcode); method_println(oldcode->m); @@ -1732,12 +1744,6 @@ struct replace_patch_data_t { u1 *entrypoint; }; -#define CODEINFO_OF_CODE(entrypoint) \ - (*(codeinfo **)((u1*)(entrypoint) + CodeinfoPointer)) - -#define METHOD_OF_CODE(entrypoint) \ - (CODEINFO_OF_CODE(entrypoint)->m) - void replace_patch_callback(classinfo *c, struct replace_patch_data_t *pd) { vftbl_t *vftbl = c->vftbl; @@ -1745,7 +1751,7 @@ void replace_patch_callback(classinfo *c, struct replace_patch_data_t *pd) if (vftbl != NULL && vftbl->vftbllength > pd->m->vftblindex && vftbl->table[pd->m->vftblindex] != &asm_abstractmethoderror - && METHOD_OF_CODE(vftbl->table[pd->m->vftblindex]) == pd->m) + && code_get_methodinfo_for_pv(vftbl->table[pd->m->vftblindex]) == pd->m) { replace_patch_class(c->vftbl, pd->m, pd->oldentrypoint, pd->entrypoint); } @@ -1786,15 +1792,15 @@ void replace_patch_future_calls(u1 *ra, sourceframe_t *callerframe, sourceframe_t *calleeframe) { - u1 *patchpos; - methodptr entrypoint; - methodptr oldentrypoint; - bool atentry; - stackframeinfo sfi; - codeinfo *calleecode; - methodinfo *calleem; - java_objectheader *obj; - vftbl_t *vftbl; + u1 *patchpos; + methodptr entrypoint; + methodptr oldentrypoint; + bool atentry; + void *pv; + codeinfo *calleecode; + methodinfo *calleem; + java_object_t *obj; + vftbl_t *vftbl; assert(ra); assert(callerframe->down == calleeframe); @@ -1817,8 +1823,8 @@ void replace_patch_future_calls(u1 *ra, /* get the position to patch, in case it was a statically bound call */ - sfi.pv = callerframe->fromcode->entrypoint; - patchpos = md_get_method_patch_address(ra, &sfi, NULL); + pv = callerframe->fromcode->entrypoint; + patchpos = md_jit_method_patch_address(pv, ra, NULL); if (patchpos == NULL) { /* the call was dispatched dynamically */ @@ -1954,14 +1960,14 @@ void replace_push_activation_record(executionstate_t *es, #if defined(REPLACE_RA_TOP_OF_FRAME) #if defined(REPLACE_LEAFMETHODS_RA_REGISTER) - if (!CODE_IS_LEAFMETHOD(calleecode)) + if (!code_is_leafmethod(calleecode)) #endif *--basesp = (ptrint) ra; #endif /* REPLACE_RA_TOP_OF_FRAME */ #if defined(REPLACE_RA_LINKAGE_AREA) #if defined(REPLACE_LEAFMETHODS_RA_REGISTER) - if (!CODE_IS_LEAFMETHOD(calleecode)) + if (!code_is_leafmethod(calleecode)) #endif basesp[LA_LR_OFFSET / sizeof(stackslot_t)] = (ptrint) ra; #endif /* REPLACE_RA_LINKAGE_AREA */ @@ -2125,7 +2131,9 @@ no_match: /* replace_find_replacement_point_for_pc *************************************** - Find the nearest replacement point at or before the given PC. + Find the nearest replacement point at or before the given PC. The + given PC has to be between (rp->pc) and (rp->pc+rp->callsize) for + the replacement point to be found. IN: code.............compilation unit the PC is in @@ -2143,21 +2151,18 @@ rplpoint *replace_find_replacement_point_for_pc(codeinfo *code, u1 *pc) rplpoint *rp; s4 i; - DOLOG( printf("searching for rp in %p ", (void*)code); - method_println(code->m); - printf("PC = %p\n", (void*)pc); ); + DOLOG( printf("searching for rp at pc:%p in %p ", (void*)pc, (void*)code); + method_println(code->m); ); found = NULL; rp = code->rplpoints; for (i=0; irplpointcount; ++i, ++rp) { DOLOG( replace_replacement_point_println(rp, 2); ); - if (rp->pc <= pc) + if (rp->pc <= pc && rp->pc + rp->callsize >= pc) found = rp; } - assert(found == NULL || found->pc + found->callsize >= pc); - return found; } @@ -2180,7 +2185,7 @@ rplpoint *replace_find_replacement_point_for_pc(codeinfo *code, u1 *pc) static void replace_pop_native_frame(executionstate_t *es, sourcestate_t *ss, - stackframeinfo *sfi) + stackframeinfo_t *sfi) { sourceframe_t *frame; codeinfo *code; @@ -2259,29 +2264,21 @@ static void replace_pop_native_frame(executionstate_t *es, # endif #endif - /* restore pv, pc, and sp */ - - if (sfi->pv == NULL) { - /* frame of a native function call */ - es->pv = md_codegen_get_pv_from_pc(sfi->ra); - } - else { - es->pv = sfi->pv; - } - es->pc = ((sfi->xpc) ? sfi->xpc : sfi->ra) - 1; - es->sp = sfi->sp; - - /* find the new codeinfo */ - - DOLOG( printf("PV = %p\n", (void*) es->pv); ); + /* restore codeinfo of the native stub */ - assert(es->pv != NULL); + code = code_get_codeinfo_for_pv(sfi->pv); - code = *(codeinfo **)(es->pv + CodeinfoPointer); + /* restore sp, pv, pc and codeinfo of the parent method */ - DOLOG( printf("CODE = %p\n", (void*) code); ); - - es->code = code; + /* XXX michi: use this instead: + es->sp = sfi->sp + code->stackframesize; */ + es->sp = sfi->sp + (*(s4 *) (sfi->pv + FrameSize)); +#if defined(REPLACE_RA_BETWEEN_FRAMES) + es->sp += SIZE_OF_STACKSLOT; /* skip return address */ +#endif + es->pv = md_codegen_get_pv_from_pc(sfi->ra); + es->pc = ((sfi->xpc) ? sfi->xpc : sfi->ra) - 1; + es->code = code_get_codeinfo_for_pv(es->pv); } @@ -2322,6 +2319,13 @@ static void replace_push_native_frame(executionstate_t *es, sourcestate_t *ss) ss->frames = frame->down; + /* skip sp for the native stub */ + + es->sp -= (*(s4 *) (frame->sfi->pv + FrameSize)); +#if defined(REPLACE_RA_BETWEEN_FRAMES) + es->sp -= SIZE_OF_STACKSLOT; /* skip return address */ +#endif + /* assert that the native frame has not moved */ assert(es->sp == frame->sfi->sp); @@ -2393,7 +2397,7 @@ static void replace_push_native_frame(executionstate_t *es, sourcestate_t *ss) *******************************************************************************/ sourcestate_t *replace_recover_source_state(rplpoint *rp, - stackframeinfo *sfi, + stackframeinfo_t *sfi, executionstate_t *es) { sourcestate_t *ss; @@ -2650,7 +2654,7 @@ static void replace_map_source_state_identity(sourcestate_t *ss) #endif -/* replace_build_execution_state_intern **************************************** +/* replace_build_execution_state *********************************************** Build an execution state for the given (mapped) source state. @@ -2668,8 +2672,8 @@ static void replace_map_source_state_identity(sourcestate_t *ss) *******************************************************************************/ -void replace_build_execution_state_intern(sourcestate_t *ss, - executionstate_t *es) +static void replace_build_execution_state(sourcestate_t *ss, + executionstate_t *es) { rplpoint *rp; sourceframe_t *prevframe; @@ -2731,148 +2735,41 @@ void replace_build_execution_state_intern(sourcestate_t *ss, } -/* replace_build_execution_state *********************************************** - - This function contains the final phase of replacement. It builds the new - execution state, releases dump memory, and returns to the calling - assembler function which finishes replacement. - - NOTE: This function is called from asm_replacement_in, with the stack - pointer at the start of the safe stack area. - - THIS FUNCTION MUST BE CALLED USING A SAFE STACK AREA! - - CAUTION: This function and its children must not use a lot of stack! - There are only REPLACE_SAFESTACK_SIZE bytes of C stack - available. - - IN: - st...............the safestack contained the necessary data - -*******************************************************************************/ - -void replace_build_execution_state(replace_safestack_t *st) -{ - replace_build_execution_state_intern(st->ss, &(st->es)); - - DOLOG( replace_executionstate_println(&(st->es)); ); - - /* release dump area */ - - dump_release(st->dumpsize); - - /* new code is entered after returning */ - - DOLOG( printf("JUMPING IN!\n"); fflush(stdout); ); -} - - -/* replace_alloc_safestack ***************************************************** - - Allocate a safe stack area to use during the final phase of replacement. - The returned area is not initialized. This must be done by the caller. - - RETURN VALUE: - a newly allocated replace_safestack_t * - -*******************************************************************************/ - -static replace_safestack_t *replace_alloc_safestack() -{ - u1 *mem; - replace_safestack_t *st; - - mem = MNEW(u1, sizeof(replace_safestack_t) + REPLACE_STACK_ALIGNMENT - 1); - - st = (replace_safestack_t *) ((ptrint)(mem + REPLACE_STACK_ALIGNMENT - 1) - & ~(REPLACE_STACK_ALIGNMENT - 1)); - -#if !defined(NDEBUG) - memset(st, 0xa5, sizeof(replace_safestack_t)); -#endif - - st->mem = mem; - - return st; -} - - -/* replace_free_safestack ****************************************************** - - Free the given safestack structure, making a copy of the contained - execution state before freeing it. - - NOTE: This function is called from asm_replacement_in. - - IN: - st...............the safestack to free - tmpes............where to copy the execution state to - - OUT: - *tmpes...........receives a copy of st->es - -*******************************************************************************/ - -void replace_free_safestack(replace_safestack_t *st, executionstate_t *tmpes) -{ - u1 *mem; - - /* copy the executionstate_t to the temporary location */ - - *tmpes = st->es; - - /* get the memory address to free */ - - mem = st->mem; - - /* destroy memory (in debug mode) */ - -#if !defined(NDEBUG) - memset(st, 0xa5, sizeof(replace_safestack_t)); -#endif - - /* free the safe stack struct */ - - MFREE(mem, u1, sizeof(replace_safestack_t) + REPLACE_STACK_ALIGNMENT - 1); -} - - /* replace_me ****************************************************************** - This function is called by asm_replacement_out when a thread reaches + This function is called by the signal handler when a thread reaches a replacement point. `replace_me` must map the execution state to the target replacement point and let execution continue there. - This function never returns! - + THIS FUNCTION MUST BE CALLED USING A SAFE STACK AREA! + IN: rp...............replacement point that has been reached - es...............execution state read by asm_replacement_out + es...............execution state read by signal handler *******************************************************************************/ -void replace_me(rplpoint *rp, executionstate_t *es) +static void replace_me(rplpoint *rp, executionstate_t *es) { - stackframeinfo *sfi; + stackframeinfo_t *sfi; sourcestate_t *ss; sourceframe_t *frame; s4 dumpsize; + codeinfo *origcode; rplpoint *origrp; - replace_safestack_t *safestack; #if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO) threadobject *thread; #endif - origrp = rp; - es->code = code_find_codeinfo_for_pc(rp->pc); + origcode = es->code; + origrp = rp; DOLOG_SHORT( printf("REPLACING(%d %p): (id %d %p) ", stat_replacements, (void*)THREADOBJECT, rp->id, (void*)rp); method_println(es->code->m); ); - DOLOG( replace_replacement_point_println(rp, 1); - replace_executionstate_println(es); ); + DOLOG( replace_replacement_point_println(rp, 1); ); REPLACE_COUNT(stat_replacements); @@ -2904,10 +2801,7 @@ void replace_me(rplpoint *rp, executionstate_t *es) /* since we enter the same method again, we turn off rps now */ /* XXX michi: can we really do this? what if the rp was active before we activated it for the gc? */ - frame = ss->frames; - while (frame->down) - frame = frame->down; - replace_deactivate_replacement_points(frame->tocode); + replace_deactivate_replacement_points(origcode); /* remember executionstate and sourcestate for this thread */ GC_EXECUTIONSTATE = es; @@ -2930,42 +2824,114 @@ void replace_me(rplpoint *rp, executionstate_t *es) DOLOG_SHORT( replace_sourcestate_println_short(ss); ); - /* avoid infinite loops by self-replacement */ +#if !defined(NDEBUG) + /* avoid infinite loops by self-replacement, only if not in testing mode */ - frame = ss->frames; - while (frame->down) - frame = frame->down; + if (!opt_TestReplacement) { + frame = ss->frames; + while (frame->down) + frame = frame->down; - if (frame->torp == origrp) { - DOLOG_SHORT( - printf("WARNING: identity replacement, turning off rps to avoid infinite loop\n"); - ); - replace_deactivate_replacement_points(frame->tocode); + if (frame->torp == origrp) { + DOLOG_SHORT( + printf("WARNING: identity replacement, turning off rps to avoid infinite loop\n"); + ); + replace_deactivate_replacement_points(origcode); + } } +#endif #if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO) } #endif - /* write execution state of new code */ + /* build the new execution state */ + + replace_build_execution_state(ss, es); + +#if !defined(NDEBUG) + /* continue execution after patched machine code, if testing mode enabled */ + + if (opt_TestReplacement) + es->pc += REPLACEMENT_PATCH_SIZE; +#endif - DOLOG( replace_executionstate_println(es); ); + /* release dump area */ - /* allocate a safe stack area and copy all needed data there */ + dump_release(dumpsize); +} - safestack = replace_alloc_safestack(); - safestack->es = *es; - safestack->ss = ss; - safestack->dumpsize = dumpsize; +/* replace_me_wrapper ********************************************************** - /* call the assembler code for the last phase of replacement */ + This function is called by the signal handler. It determines if there + is an active replacement point pending at the given PC and returns + accordingly. -#if (defined(__I386__) || defined(__X86_64__) || defined(__ALPHA__) || defined(__POWERPC__) || defined(__MIPS__)) && defined(ENABLE_JIT) - asm_replacement_in(&(safestack->es), safestack); -#endif + THIS FUNCTION MUST BE CALLED USING A SAFE STACK AREA! + + IN: + pc...............the program counter that triggered the replacement. + context..........the context (machine state) to which the + replacement should be applied. + + OUT: + context..........the context after replacement finished. + + RETURN VALUE: + true.............replacement done, everything went ok + false............no replacement done, context unchanged + +*******************************************************************************/ + +bool replace_me_wrapper(u1 *pc, void *context) +{ + codeinfo *code; + rplpoint *rp; + executionstate_t es; + + /* search the codeinfo for the given PC */ + + code = code_find_codeinfo_for_pc(pc); + assert(code); + + /* search for a replacement point at the given PC */ + + rp = replace_find_replacement_point_for_pc(code, pc); + + /* check if the replacement point belongs to given PC and is active */ + + if ((rp != NULL) && (rp->pc == pc) && (rp->flags & RPLPOINT_FLAG_ACTIVE)) { + + /* set codeinfo pointer in execution state */ + + es.code = code; + + /* read execution state from current context */ - abort(); /* NOT REACHED */ + md_replace_executionstate_read(&es, context); + + DOLOG( printf("REPLACEMENT READ: "); + replace_executionstate_println(&es); ); + + /* do the actual replacement */ + + replace_me(rp, &es); + + /* write execution state to current context */ + + md_replace_executionstate_write(&es, context); + + DOLOG( printf("REPLACEMENT WRITE: "); + replace_executionstate_println(&es); ); + + /* new code is entered after returning */ + + DOLOG( printf("JUMPING IN!\n"); fflush(stdout); ); + return true; + } + else + return false; } @@ -2976,7 +2942,7 @@ void replace_me(rplpoint *rp, executionstate_t *es) #if defined(ENABLE_GC_CACAO) void replace_gc_from_native(threadobject *thread, u1 *pc, u1 *sp) { - stackframeinfo *sfi; + stackframeinfo_t *sfi; executionstate_t *es; sourcestate_t *ss; @@ -3003,6 +2969,21 @@ void replace_gc_from_native(threadobject *thread, u1 *pc, u1 *sp) } #endif +#if defined(ENABLE_GC_CACAO) +void replace_gc_into_native(threadobject *thread) +{ + executionstate_t *es; + sourcestate_t *ss; + + /* get the executionstate and sourcestate for the given thread */ + es = GC_EXECUTIONSTATE; + ss = GC_SOURCESTATE; + + /* rebuild the stack of the given thread */ + replace_build_execution_state(ss, es); +} +#endif + /******************************************************************************/ /* NOTE: No important code below. */ @@ -3309,7 +3290,7 @@ void replace_executionstate_println(executionstate_t *es) if (es->code) { methoddesc *md = es->code->m->parseddesc; - slots = code_get_stack_frame_size(es->code); + slots = es->code->stackframesize; extraslots = 1 + md->memuse; } else @@ -3346,8 +3327,8 @@ void replace_executionstate_println(executionstate_t *es) #if !defined(NDEBUG) static void java_value_print(s4 type, replace_val_t value) { - java_objectheader *obj; - utf *u; + java_object_t *obj; + utf *u; printf("%016llx",(unsigned long long) value.l); @@ -3568,14 +3549,14 @@ void replace_sourcestate_println_short(sourcestate_t *ss) #endif #if !defined(NDEBUG) -static void replace_stackframeinfo_println(stackframeinfo *sfi) +static void replace_stackframeinfo_println(stackframeinfo_t *sfi) { printf("prev=%p pv=%p sp=%p ra=%p xpc=%p method=", (void*)sfi->prev, (void*)sfi->pv, (void*)sfi->sp, (void*)sfi->ra, (void*)sfi->xpc); - if (sfi->method) - method_println(sfi->method); + if (sfi->code) + method_println(sfi->code->m); else printf("(nil)\n"); }