X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fvm%2Fjit%2Freplace.c;h=c0b170231bfd8be55c1e4c2b871644bebbf7fc5f;hb=caf4bfb972a703ceeaa4bdf5afb820bce15fd7e6;hp=30ad2bf71126842db95b8043162add820425a39a;hpb=2457ad8bcdb80a1026380a158052aa91ad06651d;p=cacao.git diff --git a/src/vm/jit/replace.c b/src/vm/jit/replace.c index 30ad2bf71..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" @@ -76,8 +75,8 @@ #undef REPLACE_LEAFMETHODS_RA_REGISTER #undef REPLACE_REG_RA -/* i386 and x86_64 */ -#if defined(__I386__) || defined(__X86_64__) +/* i386, x86_64 and m68k */ +#if defined(__I386__) || defined(__X86_64__) || defined(__M68K__) #define REPLACE_RA_BETWEEN_FRAMES /* alpha */ #elif defined(__ALPHA__) @@ -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 @@ -109,17 +112,14 @@ typedef u8 stackslot_t; /*** debugging ****************************************************************/ -/*#define REPLACE_VERBOSE*/ - #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) && defined(REPLACE_VERBOSE) -int replace_verbose = 0; -#define DOLOG(code) do{ if (replace_verbose > 1) { code; } } while(0) -#define DOLOG_SHORT(code) do{ if (replace_verbose > 0) { code; } } while(0) +#if !defined(NDEBUG) +#define DOLOG(code) do{ if (opt_TraceReplacement > 1) { code; } } while(0) +#define DOLOG_SHORT(code) do{ if (opt_TraceReplacement > 0) { code; } } while(0) #else #define DOLOG(code) #define DOLOG_SHORT(code) @@ -429,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) @@ -478,6 +473,17 @@ bool replace_create_replacement_points(jitdata *jd) for (; iptr != iend; ++iptr) { switch (iptr->opc) { +#if defined(ENABLE_GC_CACAO) + case ICMD_BUILTIN: + md = iptr->sx.s23.s3.bte->md; + count++; + COUNT_javalocals(javalocals, m, alloccount); + alloccount += iptr->s1.argcount; + if (iinfo) + alloccount -= iinfo->throughcount; + break; +#endif + case ICMD_INVOKESTATIC: case ICMD_INVOKESPECIAL: case ICMD_INVOKEVIRTUAL: @@ -629,6 +635,19 @@ bool replace_create_replacement_points(jitdata *jd) for (; iptr != iend; ++iptr) { switch (iptr->opc) { +#if defined(ENABLE_GC_CACAO) + case ICMD_BUILTIN: + md = iptr->sx.s23.s3.bte->md; + + i = (iinfo) ? iinfo->throughcount : 0; + replace_create_replacement_point(jd, iinfo, rp++, + RPLPOINT_TYPE_CALL, iptr, &ra, + javalocals, iptr->sx.s23.s2.args, + iptr->s1.argcount - i, + md->paramcount); + break; +#endif + case ICMD_INVOKESTATIC: case ICMD_INVOKESPECIAL: case ICMD_INVOKEVIRTUAL: @@ -716,6 +735,9 @@ bool replace_create_replacement_points(jitdata *jd) 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; @@ -779,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); @@ -787,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; @@ -819,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; @@ -829,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; } @@ -891,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; @@ -920,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 @@ -930,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) { @@ -938,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 @@ -955,6 +990,11 @@ static void replace_read_value(executionstate_t *es, if (ra->type == TYPE_FLT) javaval->f = javaval->d; } +#if defined(HAS_ADDRESS_REGISTER_FILE) + else if (IS_ADR_TYPE(ra->type)) { + javaval->p = es->adrregs[ra->regoff]; + } +#endif else { #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) if (ra->type == TYPE_LNG) { @@ -975,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) { @@ -990,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 @@ -1013,6 +1051,10 @@ static void replace_write_value(executionstate_t *es, es->intregs[GET_LOW_REG(ra->regoff)] = javaval->words.lo; es->intregs[GET_HIGH_REG(ra->regoff)] = javaval->words.hi; break; +#endif +#if defined(HAS_ADDRESS_REGISTER_FILE) + case TYPE_ADR: + es->adrregs[ra->regoff] = javaval->p; #endif default: es->intregs[ra->regoff] = javaval->p; @@ -1021,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 @@ -1052,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 *******************************************************************************/ @@ -1106,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 */ @@ -1153,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--; } @@ -1178,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) */ @@ -1255,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--; @@ -1273,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++; } @@ -1283,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 @@ -1325,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 */ @@ -1346,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++; } @@ -1403,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; } @@ -1422,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++; } @@ -1468,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); @@ -1499,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 */ @@ -1531,6 +1581,17 @@ u1* replace_pop_activation_record(executionstate_t *es, 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) + ; + es->adrregs[reg] = *--basesp; + } +#endif + /* adjust the stackpointer */ es->sp += SIZE_OF_STACKSLOT * es->code->stackframesize; @@ -1547,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 */ @@ -1576,6 +1632,11 @@ u1* replace_pop_activation_record(executionstate_t *es, for (i=0; ifltregs[i]) = 0x33dead3333dead33ULL; +# if defined(HAS_ADDRESS_REGISTER_FILE) + for (i=0; iadrregs[i] = (ptrint) 0x33dead3333dead33ULL; +# endif #endif /* !defined(NDEBUG) */ return (code) ? ra : NULL; @@ -1607,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); @@ -1683,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; @@ -1696,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); } @@ -1737,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); @@ -1768,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 */ @@ -1905,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 */ @@ -1947,6 +2002,22 @@ void replace_push_activation_record(executionstate_t *es, #endif } +#if defined(HAS_ADDRESS_REGISTER_FILE) + /* save adr registers */ + + reg = ADR_REG_CNT; + for (i=0; isavedadrcount; ++i) { + while (nregdescadr[--reg] != REG_SAV) + ; + *--basesp = es->adrregs[reg]; + + /* XXX may not clobber saved regs used by native code! */ +#if !defined(NDEBUG) && 0 + es->adrregs[reg] = (ptrint) 0x44dead4444dead44ULL; +#endif + } +#endif + /* write slots used for synchronization */ count = code_get_sync_slot_count(calleecode); @@ -2060,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 @@ -2078,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->pc + found->callsize >= pc); - return found; } @@ -2115,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; @@ -2147,9 +2217,17 @@ static void replace_pop_native_frame(executionstate_t *es, frame->nativesavflt[j++] = es->fltregs[i]; } +#if defined(HAS_ADDRESS_REGISTER_FILE) + j = 0; + for (i=0; inativesavadr[j++] = es->adrregs[i]; + } +#endif + /* restore saved registers */ -#if defined(ENABLE_GC_CACAO) +#if defined(ENABLE_GC_CACAO) && !defined(HAS_ADDRESS_REGISTER_FILE) j = 0; for (i=0; ifltregs[i] = 0.0; } - /* 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); +#if defined(HAS_ADDRESS_REGISTER_FILE) +# if defined(ENABLE_GC_CACAO) + j = 0; + for (i=0; iadrregs[i] = sfi->adrregs[j++]; } - else { - es->pv = sfi->pv; +# else + for (i=0; iadrregs[i] = 0; } - es->pc = ((sfi->xpc) ? sfi->xpc : sfi->ra) - 1; - es->sp = sfi->sp; - - /* find the new codeinfo */ +# endif +#endif - 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); } @@ -2234,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); @@ -2242,10 +2334,17 @@ static void replace_push_native_frame(executionstate_t *es, sourcestate_t *ss) #if defined(ENABLE_GC_CACAO) j = 0; +# if !defined(HAS_ADDRESS_REGISTER_FILE) for (i=0; isfi->intregs[j++] = es->intregs[i]; } +# else + for (i=0; isfi->adrregs[j++] = es->adrregs[i]; + } +# endif /* XXX leave float registers untouched here */ #endif @@ -2264,6 +2363,14 @@ static void replace_push_native_frame(executionstate_t *es, sourcestate_t *ss) es->fltregs[i] = frame->nativesavflt[j++]; } +#if defined(HAS_ADDRESS_REGISTER_FILE) + j = 0; + for (i=0; iadrregs[i] = frame->nativesavadr[j++]; + } +#endif + /* skip the native frame on the machine stack */ es->sp -= frame->nativeframesize; @@ -2290,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; @@ -2547,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. @@ -2565,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; @@ -2628,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); @@ -2801,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; @@ -2827,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 */ - DOLOG( replace_executionstate_println(es); ); + replace_build_execution_state(ss, es); - /* allocate a safe stack area and copy all needed data there */ +#if !defined(NDEBUG) + /* continue execution after patched machine code, if testing mode enabled */ - safestack = replace_alloc_safestack(); + if (opt_TestReplacement) + es->pc += REPLACEMENT_PATCH_SIZE; +#endif - safestack->es = *es; - safestack->ss = ss; - safestack->dumpsize = dumpsize; + /* release dump area */ - /* call the assembler code for the last phase of replacement */ + dump_release(dumpsize); +} -#if (defined(__I386__) || defined(__X86_64__) || defined(__ALPHA__) || defined(__POWERPC__) || defined(__MIPS__)) && defined(ENABLE_JIT) - asm_replacement_in(&(safestack->es), safestack); -#endif - abort(); /* NOT REACHED */ +/* replace_me_wrapper ********************************************************** + + 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. + + 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 */ + + 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; } @@ -2873,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; @@ -2900,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. */ @@ -3116,6 +3200,9 @@ void replace_show_replacement_points(codeinfo *code) printf("\ttotal allocations : %d\n",code->regalloccount); printf("\tsaved int regs : %d\n",code->savedintcount); printf("\tsaved flt regs : %d\n",code->savedfltcount); +#if defined(HAS_ADDRESS_REGISTER_FILE) + printf("\tsaved adr regs : %d\n",code->savedadrcount); +#endif printf("\tmemuse : %d\n",code->memuse); printf("\n"); @@ -3184,6 +3271,17 @@ void replace_executionstate_println(executionstate_t *es) if (i%4 == 3) printf("\n"); } +# if defined(HAS_ADDRESS_REGISTER_FILE) + for (i=0; iadrregs[i]); + if (i%4 == 3) + printf("\n"); + } +# endif #endif sp = (stackslot_t *) es->sp; @@ -3192,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 @@ -3229,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); @@ -3451,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"); }