-/* vm/jit/replace.c - on-stack replacement of methods
+/* src/vm/jit/replace.c - on-stack replacement of methods
- Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+ Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
J. Wenninger, Institut f. Computersprachen - TU Wien
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- Contact: cacao@cacaojvm.org
-
- Authors: Edwin Steiner
-
- $Id$
-
*/
#include "config.h"
#include "arch.h"
#include "mm/memory.h"
+
+#include "threads/threads-common.h"
+
#include "toolbox/logging.h"
-#include "vm/options.h"
+
#include "vm/stringlocal.h"
+
#include "vm/jit/abi.h"
-#include "vm/jit/jit.h"
-#include "vm/jit/replace.h"
-#include "vm/jit/stack.h"
#include "vm/jit/asmpart.h"
#include "vm/jit/disass.h"
-#include "vm/jit/show.h"
+#include "vm/jit/jit.h"
+#include "vm/jit/md.h"
#include "vm/jit/methodheader.h"
+#include "vm/jit/replace.h"
+#include "vm/jit/show.h"
+#include "vm/jit/stack.h"
+
+#include "vmcore/options.h"
+#include "vmcore/classcache.h"
-#include "native/include/java_lang_String.h"
#define REPLACE_PATCH_DYNAMIC_CALL
/*#define REPLACE_PATCH_ALL*/
+#if defined(ENABLE_VMLOG)
+#include <vmlog_cacao.h>
+#endif
/*** architecture-dependent configuration *************************************/
#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__)
#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
/*** debugging ****************************************************************/
-/*#define REPLACE_VERBOSE*/
-
#if !defined(NDEBUG)
-static void java_value_print(s4 type, u8 value);
-#endif /* !defined(NDEBUG) */
+static void java_value_print(s4 type, replace_val_t value);
+static void replace_stackframeinfo_println(stackframeinfo *sfi);
+#endif
-#if !defined(NDEBUG) && defined(REPLACE_VERBOSE)
-#define DOLOG(code) do{ if (1) { code; } } while(0)
-#define DOLOG_SHORT(code) do{ if (1) { 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)
continue;
ra->index = i;
- if (index < UNUSED) {
- ra->regoff = (UNUSED - index) - 1;
- ra->type = TYPE_RET;
- ra->flags = 0;
- }
- else {
+ if (index >= 0) {
v = VAR(index);
ra->flags = v->flags & (INMEMORY);
ra->regoff = v->vv.regoff;
ra->type = v->type;
}
+ else {
+ ra->regoff = RETADDR_FROM_JAVALOCAL(index);
+ ra->type = TYPE_RET;
+ ra->flags = 0;
+ }
ra++;
}
}
replace_create_replacement_point(jd, iinfo, rp++,
bptr->type, bptr->iinstr, &ra,
bptr->javalocals, bptr->invars + i, bptr->indepth - i, 0);
+
+ if (JITDATA_HAS_FLAG_COUNTDOWN(jd))
+ rp[-1].flags |= RPLPOINT_FLAG_COUNTDOWN;
}
/* iterate over the instructions */
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;
savedmcode -= REPLACEMENT_PATCH_SIZE;
-#if (defined(__I386__) || defined(__X86_64__) || defined(__ALPHA__) || defined(__POWERPC__) || defined(__MIPS__)) && defined(ENABLE_JIT)
+#if (defined(__I386__) || defined(__X86_64__) || defined(__ALPHA__) || defined(__POWERPC__) || defined(__MIPS__) || defined(__S390__)) && defined(ENABLE_JIT)
md_patch_replacement_point(code, index, rp, savedmcode);
#endif
rp->flags |= RPLPOINT_FLAG_ACTIVE;
s4 count;
u1 *savedmcode;
+ if (code->savedmcode == NULL) {
+ /* disarm countdown points by patching the branches */
+
+ i = code->rplpointcount;
+ rp = code->rplpoints;
+ for (; i--; rp++) {
+ if ((rp->flags & (RPLPOINT_FLAG_ACTIVE | RPLPOINT_FLAG_COUNTDOWN))
+ == RPLPOINT_FLAG_COUNTDOWN)
+ {
+#if 0
+ *(s4*) (rp->pc + 9) = 0; /* XXX machine dependent! */
+#endif
+ }
+ }
+ return;
+ }
+
assert(code->savedmcode != NULL);
savedmcode = code->savedmcode;
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)
+#if (defined(__I386__) || defined(__X86_64__) || defined(__ALPHA__) || defined(__POWERPC__) || defined(__MIPS__) || defined(__S390__)) && defined(ENABLE_JIT)
md_patch_replacement_point(code, -1, rp, savedmcode);
#endif
IN:
es...............execution state
- sp...............stack pointer of the execution state (XXX eliminate?)
ra...............allocation
javaval..........where to put the value
*******************************************************************************/
static void replace_read_value(executionstate_t *es,
- stackslot_t *sp,
rplalloc *ra,
- u8 *javaval)
+ replace_val_t *javaval)
{
if (ra->flags & INMEMORY) {
/* XXX HAS_4BYTE_STACKSLOT may not be the right discriminant here */
#ifdef HAS_4BYTE_STACKSLOT
if (IS_2_WORD_TYPE(ra->type)) {
- *javaval = *(u8*)(sp + ra->regoff);
+ javaval->l = *(u8*)(es->sp + ra->regoff);
}
else {
#endif
- *javaval = sp[ra->regoff];
+ javaval->p = *(ptrint*)(es->sp + ra->regoff);
#ifdef HAS_4BYTE_STACKSLOT
}
#endif
else {
/* allocated register */
if (IS_FLT_DBL_TYPE(ra->type)) {
- *javaval = es->fltregs[ra->regoff];
+ javaval->d = es->fltregs[ra->regoff];
+
+ 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 {
- *javaval = es->intregs[ra->regoff];
+#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
+ if (ra->type == TYPE_LNG) {
+ javaval->words.lo = es->intregs[GET_LOW_REG(ra->regoff)];
+ javaval->words.hi = es->intregs[GET_HIGH_REG(ra->regoff)];
+ }
+ else
+#endif /* defined(SUPPORT_COMBINE_INTEGER_REGISTERS) */
+ javaval->p = es->intregs[ra->regoff];
}
}
}
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,
- u8 *javaval)
+ replace_val_t *javaval)
{
if (ra->flags & INMEMORY) {
/* 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;
+ *(u8*)(es->sp + ra->regoff) = javaval->l;
}
else {
#endif
- sp[ra->regoff] = *javaval;
+ *(ptrint*)(es->sp + ra->regoff) = javaval->p;
#ifdef HAS_4BYTE_STACKSLOT
}
#endif
}
else {
/* allocated register */
- if (IS_FLT_DBL_TYPE(ra->type)) {
- es->fltregs[ra->regoff] = *javaval;
- }
- else {
- es->intregs[ra->regoff] = *javaval;
+ switch (ra->type) {
+ case TYPE_FLT:
+ es->fltregs[ra->regoff] = (double) javaval->f;
+ break;
+ case TYPE_DBL:
+ es->fltregs[ra->regoff] = javaval->d;
+ break;
+#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
+ case TYPE_LNG:
+ 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;
}
}
}
-/* 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 (the new head of the frame list).
+
+ RETURN VALUE:
+ returns the new frame
+
+*******************************************************************************/
+
+static sourceframe_t *replace_new_sourceframe(sourcestate_t *ss)
+{
+ sourceframe_t *frame;
+
+ frame = DNEW(sourceframe_t);
+ MZERO(frame, sourceframe_t, 1);
+
+ frame->down = ss->frames;
+ ss->frames = frame;
+
+ return frame;
+}
+
+
+/* replace_read_executionstate *************************************************
+
+ 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
*******************************************************************************/
/* RPLPOINT_TYPE_BODY |--> */ RPLPOINT_TYPE_STD
};
+
static void replace_read_executionstate(rplpoint *rp,
executionstate_t *es,
sourcestate_t *ss,
/* calculate base stack pointer */
- basesp = sp + code_get_stack_frame_size(code);
+ basesp = sp + code->stackframesize;
/* create the source frame */
- frame = DNEW(sourceframe_t);
- frame->down = ss->frames;
+ frame = replace_new_sourceframe(ss);
frame->method = rp->method;
frame->id = rp->id;
assert(rp->type >= 0 && rp->type < sizeof(replace_normalize_type_map)/sizeof(s4));
frame->type = replace_normalize_type_map[rp->type];
- frame->instance = 0;
- frame->syncslotcount = 0;
- frame->syncslots = NULL;
frame->fromrp = rp;
frame->fromcode = code;
- frame->torp = NULL;
- frame->tocode = NULL;
-
- ss->frames = frame;
/* read local variables */
count = m->maxlocals;
frame->javalocalcount = count;
- frame->javalocals = DMNEW(u8, count);
+ frame->javalocals = DMNEW(replace_val_t, count);
frame->javalocaltype = DMNEW(u1, count);
-#if !defined(NDEBUG)
/* mark values as undefined */
for (i=0; i<count; ++i) {
- frame->javalocals[i] = (u8) 0x00dead0000dead00ULL;
+#if !defined(NDEBUG)
+ frame->javalocals[i].l = (u8) 0x00dead0000dead00ULL;
+#endif
frame->javalocaltype[i] = TYPE_VOID;
}
/* some entries in the intregs array are not meaningful */
/*es->intregs[REG_ITMP3] = (u8) 0x11dead1111dead11ULL;*/
- es->intregs[REG_SP ] = (u8) 0x11dead1111dead11ULL;
+#if !defined(NDEBUG)
+ es->intregs[REG_SP ] = (ptrint) 0x11dead1111dead11ULL;
#ifdef REG_PV
- es->intregs[REG_PV ] = (u8) 0x11dead1111dead11ULL;
+ es->intregs[REG_PV ] = (ptrint) 0x11dead1111dead11ULL;
#endif
#endif /* !defined(NDEBUG) */
assert(i < m->maxlocals);
frame->javalocaltype[i] = ra->type;
if (ra->type == TYPE_RET)
- frame->javalocals[i] = ra->regoff;
+ 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--;
}
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) */
/* read stack slots */
frame->javastackdepth = count;
- frame->javastack = DMNEW(u8, count);
+ frame->javastack = DMNEW(replace_val_t, count);
frame->javastacktype = DMNEW(u1, count);
#if !defined(NDEBUG)
/* mark values as undefined */
for (i=0; i<count; ++i) {
- frame->javastack[i] = (u8) 0x00dead0000dead00ULL;
+ frame->javastack[i].l = (u8) 0x00dead0000dead00ULL;
frame->javastacktype[i] = TYPE_VOID;
}
#endif /* !defined(NDEBUG) */
assert(count);
assert(ra->index == RPLALLOC_STACK);
- frame->javastack[i] = sp[-1];
+ assert(ra->type == TYPE_ADR);
+ frame->javastack[i].p = sp[-1];
frame->javastacktype[i] = TYPE_ADR; /* XXX RET */
count--;
i++;
assert(count);
assert(ra->index == RPLALLOC_STACK);
- frame->javastack[i] = es->intregs[REG_ITMP1];
+ assert(ra->type == TYPE_ADR);
+ frame->javastack[i].p = es->intregs[REG_ITMP1];
frame->javastacktype[i] = TYPE_ADR; /* XXX RET */
count--;
i++;
assert(count);
assert(ra->index == RPLALLOC_STACK);
- frame->javastack[i] = 0;
+ frame->javastack[i].l = 0;
frame->javastacktype[i] = TYPE_VOID;
count--;
i++;
assert(calleeframe->syncslots == NULL);
calleeframe->syncslotcount = 1;
- calleeframe->syncslots = DMNEW(u8, 1);
- replace_read_value(es,sp,ra,calleeframe->syncslots);
+ calleeframe->syncslots = DMNEW(replace_val_t, 1);
+ replace_read_value(es,ra,calleeframe->syncslots);
}
frame->javastackdepth--;
}
else {
if (ra->type == TYPE_RET)
- frame->javastack[i] = ra->regoff;
+ 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++;
}
/* 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
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 */
/* 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++;
}
assert(ra->index == RPLALLOC_STACK);
assert(i < frame->javastackdepth);
assert(frame->javastacktype[i] == TYPE_ADR);
- sp[-1] = frame->javastack[i];
+ sp[-1] = frame->javastack[i].p;
count--;
i++;
ra++;
assert(ra->index == RPLALLOC_STACK);
assert(i < frame->javastackdepth);
assert(frame->javastacktype[i] == TYPE_ADR);
- es->intregs[REG_ITMP1] = frame->javastack[i];
+ es->intregs[REG_ITMP1] = frame->javastack[i].p;
count--;
i++;
ra++;
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;
}
/* 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++;
}
DOLOG( printf("return address: %p\n", (void*)ra); );
- /* find the new codeinfo */
-
- pv = md_codegen_get_pv_from_pc(ra);
-
- DOLOG( printf("PV = %p\n", (void*) pv); );
-
- if (pv == NULL)
- return NULL;
-
- code = *(codeinfo **)(pv + CodeinfoPointer);
-
- DOLOG( printf("CODE = %p\n", (void*) code); );
-
- if (code == NULL)
- return NULL;
+ assert(ra);
/* calculate the base of the stack frame */
assert(frame->syncslots == NULL);
count = code_get_sync_slot_count(es->code);
frame->syncslotcount = count;
- frame->syncslots = DMNEW(u8, count);
+ frame->syncslots = DMNEW(replace_val_t, count);
for (i=0; i<count; ++i) {
- frame->syncslots[i] = sp[es->code->memuse + i];
+ frame->syncslots[i].p = sp[es->code->memuse + i]; /* XXX */
}
/* restore return address, if part of frame */
while (nregdescfloat[--reg] != REG_SAV)
;
basesp -= STACK_SLOTS_PER_FLOAT;
- es->fltregs[reg] = *(u8*)basesp;
+ es->fltregs[reg] = *(double*)basesp;
}
- /* Set the new pc. Subtract one so we do not hit the replacement point */
- /* of the instruction following the call, if there is one. */
+#if defined(HAS_ADDRESS_REGISTER_FILE)
+ /* restore saved adr registers */
- es->pc = ra - 1;
+ 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; /* skip return address */
#endif
+ /* Set the new pc. Subtract one so we do not hit the replacement point */
+ /* of the instruction following the call, if there is one. */
+
+ es->pc = ra - 1;
+
+ /* 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);
+
+ DOLOG( printf("CODE = %p\n", (void*) code); );
+
+ /* return NULL if we reached native code */
+
es->pv = pv;
es->code = code;
+ /* in debugging mode clobber non-saved registers */
+
#if !defined(NDEBUG)
/* for debugging */
for (i=0; i<INT_REG_CNT; ++i)
&& (i != REPLACE_REG_RA)
#endif
)
- es->intregs[i] = 0x33dead3333dead33ULL;
+ es->intregs[i] = (ptrint) 0x33dead3333dead33ULL;
for (i=0; i<FLT_REG_CNT; ++i)
if (nregdescfloat[i] != REG_SAV)
- es->fltregs[i] = 0x33dead3333dead33ULL;
+ *(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) */
- return ra;
+ return (code) ? ra : NULL;
}
}
+/* replace_patch_class *********************************************************
+
+ Patch a method in the given class.
+
+ IN:
+ vftbl............vftbl of the class
+ m................the method to patch
+ oldentrypoint....the old entrypoint to replace
+ entrypoint.......the new entrypoint
+
+*******************************************************************************/
+
+void replace_patch_class(vftbl_t *vftbl,
+ methodinfo *m,
+ u1 *oldentrypoint,
+ u1 *entrypoint)
+{
+ s4 i;
+ methodptr *mpp;
+ methodptr *mppend;
+
+ /* patch the vftbl of the class */
+
+ replace_patch_method_pointer(vftbl->table + m->vftblindex,
+ entrypoint,
+ "virtual ");
+
+ /* patch the interface tables */
+
+ assert(oldentrypoint);
+
+ for (i=0; i < vftbl->interfacetablelength; ++i) {
+ mpp = vftbl->interfacetable[-i];
+ mppend = mpp + vftbl->interfacevftbllength[i];
+ for (; mpp != mppend; ++mpp)
+ if (*mpp == oldentrypoint) {
+ replace_patch_method_pointer(mpp, entrypoint, "interface");
+ }
+ }
+}
+
+
+/* replace_patch_class_hierarchy ***********************************************
+
+ Patch a method in all loaded classes.
+
+ IN:
+ m................the method to patch
+ oldentrypoint....the old entrypoint to replace
+ entrypoint.......the new entrypoint
+
+*******************************************************************************/
+
+struct replace_patch_data_t {
+ methodinfo *m;
+ u1 *oldentrypoint;
+ 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;
+
+ 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)
+ {
+ replace_patch_class(c->vftbl, pd->m, pd->oldentrypoint, pd->entrypoint);
+ }
+}
+
+void replace_patch_class_hierarchy(methodinfo *m,
+ u1 *oldentrypoint,
+ u1 *entrypoint)
+{
+ struct replace_patch_data_t pd;
+
+ pd.m = m;
+ pd.oldentrypoint = oldentrypoint;
+ pd.entrypoint = entrypoint;
+
+ DOLOG_SHORT( printf("patching class hierarchy: ");
+ method_println(m); );
+
+ classcache_foreach_loaded_class(
+ (classcache_foreach_functionptr_t) &replace_patch_callback,
+ (void*) &pd);
+}
+
+
/* replace_patch_future_calls **************************************************
Analyse a call site and depending on the kind of call patch the call, the
sourceframe_t *callerframe,
sourceframe_t *calleeframe)
{
- u1 *patchpos;
- methodptr entrypoint;
- methodptr oldentrypoint;
- methodptr *mpp;
- methodptr *mppend;
- bool atentry;
- stackframeinfo sfi;
- codeinfo *calleecode;
- methodinfo *calleem;
- java_objectheader *obj;
- struct _vftbl *vftbl;
- s4 i;
+ u1 *patchpos;
+ methodptr entrypoint;
+ methodptr oldentrypoint;
+ bool atentry;
+ stackframeinfo sfi;
+ codeinfo *calleecode;
+ methodinfo *calleem;
+ java_object_t *obj;
+ vftbl_t *vftbl;
assert(ra);
assert(callerframe->down == calleeframe);
assert((calleem->flags & ACC_STATIC) == 0);
+ oldentrypoint = calleeframe->fromcode->entrypoint;
+
/* we need to know the instance */
- if (!calleeframe->instance) {
+ if (!calleeframe->instance.a) {
DOLOG_SHORT( printf("WARNING: object instance unknown!\n"); );
+ replace_patch_class_hierarchy(calleem, oldentrypoint, entrypoint);
return;
}
/* get the vftbl */
- obj = (java_objectheader *) (ptrint) calleeframe->instance;
+ obj = calleeframe->instance.a;
vftbl = obj->vftbl;
assert(vftbl->class->vftbl == vftbl);
DOLOG_SHORT( printf("\tclass: "); class_println(vftbl->class); );
- /* patch the vftbl of the class */
-
- replace_patch_method_pointer(vftbl->table + calleem->vftblindex,
- entrypoint,
- "virtual ");
-
- /* patch the interface tables */
-
- oldentrypoint = calleeframe->fromcode->entrypoint;
- assert(oldentrypoint);
-
- for (i=0; i < vftbl->interfacetablelength; ++i) {
- mpp = vftbl->interfacetable[-i];
- mppend = mpp + vftbl->interfacevftbllength[i];
- for (; mpp != mppend; ++mpp)
- if (*mpp == oldentrypoint) {
- replace_patch_method_pointer(mpp, entrypoint, "interface");
- }
- }
+ replace_patch_class(vftbl, calleem, oldentrypoint, entrypoint);
}
else {
/* the call was statically bound */
IN:
es...............execution state
rpcall...........the replacement point at the call site
- callerframe......source frame of the caller
+ callerframe......source frame of the caller, or NULL for creating the
+ first frame
calleeframe......source frame of the callee, must have been mapped
OUT:
codeinfo *calleecode;
assert(es);
- assert(rpcall && rpcall->type == RPLPOINT_TYPE_CALL);
- assert(callerframe);
+ assert(!rpcall || callerframe);
+ assert(!rpcall || rpcall->type == RPLPOINT_TYPE_CALL);
+ assert(!rpcall || rpcall == callerframe->torp);
assert(calleeframe);
- assert(calleeframe == callerframe->down);
+ assert(!callerframe || calleeframe == callerframe->down);
/* the compilation unit we are entering */
/* calculate the return address */
- ra = rpcall->pc + rpcall->callsize;
+ if (rpcall)
+ ra = rpcall->pc + rpcall->callsize;
+ else
+ ra = es->pc + 1 /* XXX this is ugly */;
/* write the return address */
#endif /* REPLACE_RA_BETWEEN_FRAMES */
#if defined(REPLACE_REG_RA)
- es->intregs[REPLACE_REG_RA] = (u8) (ptrint) ra;
+ es->intregs[REPLACE_REG_RA] = (ptrint) ra;
#endif
/* we move into a new code unit */
es->code = calleecode;
- /* set the new pc XXX not needed */
+ /* set the new pc XXX not needed? */
es->pc = calleecode->entrypoint;
/* in debug mode, invalidate stack frame first */
-#if !defined(NDEBUG)
+ /* XXX may not invalidate linkage area used by native code! */
+#if !defined(NDEBUG) && 0
for (i=0; i<(basesp - sp); ++i) {
sp[i] = 0xdeaddeadU;
}
;
*--basesp = es->intregs[reg];
-#if !defined(NDEBUG)
- es->intregs[reg] = 0x44dead4444dead44ULL;
+ /* XXX may not clobber saved regs used by native code! */
+#if !defined(NDEBUG) && 0
+ es->intregs[reg] = (ptrint) 0x44dead4444dead44ULL;
#endif
}
while (nregdescfloat[--reg] != REG_SAV)
;
basesp -= STACK_SLOTS_PER_FLOAT;
- *(u8*)basesp = es->fltregs[reg];
+ *(double*)basesp = es->fltregs[reg];
-#if !defined(NDEBUG)
- es->fltregs[reg] = 0x44dead4444dead44ULL;
+ /* XXX may not clobber saved regs used by native code! */
+#if !defined(NDEBUG) && 0
+ *(u8*)&(es->fltregs[reg]) = 0x44dead4444dead44ULL;
#endif
}
+#if defined(HAS_ADDRESS_REGISTER_FILE)
+ /* save adr registers */
+
+ reg = ADR_REG_CNT;
+ for (i=0; i<calleecode->savedadrcount; ++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);
assert(count == calleeframe->syncslotcount);
for (i=0; i<count; ++i) {
- sp[calleecode->memuse + i] = calleeframe->syncslots[i];
+ sp[calleecode->memuse + i] = calleeframe->syncslots[i].p;
}
/* set the PV */
/* redirect future invocations */
+ if (callerframe && rpcall) {
#if defined(REPLACE_PATCH_ALL)
- if (rpcall->type == callerframe->fromrp->type)
+ if (rpcall->type == callerframe->fromrp->type)
#else
- if (rpcall == callerframe->fromrp)
+ if (rpcall == callerframe->fromrp)
#endif
- replace_patch_future_calls(ra, callerframe, calleeframe);
+ replace_patch_future_calls(ra, callerframe, calleeframe);
+ }
}
s4 stacki;
rplalloc *ra;
+ assert(code);
assert(frame);
DOLOG( printf("searching replacement point for:\n");
if (ra->type == TYPE_RET) {
if (ra->index == RPLALLOC_STACK) {
assert(stacki < frame->javastackdepth);
- if (frame->javastack[stacki] != ra->regoff)
+ if (frame->javastack[stacki].i != ra->regoff)
goto no_match;
stacki++;
}
else {
assert(ra->index >= 0 && ra->index < frame->javalocalcount);
- if (frame->javalocals[ra->index] != ra->regoff)
+ if (frame->javalocals[ra->index].i != ra->regoff)
goto no_match;
}
}
rplpoint *rp;
s4 i;
+ DOLOG( printf("searching for rp in %p ", (void*)code);
+ method_println(code->m); );
+
found = NULL;
rp = code->rplpoints;
- for (i=0; i<code->rplpointcount; ++i, ++rp)
+ for (i=0; i<code->rplpointcount; ++i, ++rp) {
+ DOLOG( replace_replacement_point_println(rp, 2); );
if (rp->pc <= pc)
found = rp;
+ }
return found;
}
+/* replace_pop_native_frame ****************************************************
+
+ Unroll a native frame in the execution state and create a source frame
+ for it.
+
+ IN:
+ es...............current execution state
+ ss...............the current source state
+ sfi..............stackframeinfo for the native frame
+
+ OUT:
+ es...............execution state after unrolling the native frame
+ ss...............gets the added native source frame
+
+*******************************************************************************/
+
+static void replace_pop_native_frame(executionstate_t *es,
+ sourcestate_t *ss,
+ stackframeinfo *sfi)
+{
+ sourceframe_t *frame;
+ codeinfo *code;
+ s4 i,j;
+
+ assert(sfi);
+
+ frame = replace_new_sourceframe(ss);
+
+ frame->sfi = sfi;
+
+ /* remember pc and size of native frame */
+
+ frame->nativepc = es->pc;
+ frame->nativeframesize = sfi->sp - es->sp;
+ assert(frame->nativeframesize >= 0);
+
+ /* remember values of saved registers */
+
+ j = 0;
+ for (i=0; i<INT_REG_CNT; ++i) {
+ if (nregdescint[i] == REG_SAV)
+ frame->nativesavint[j++] = es->intregs[i];
+ }
+
+ j = 0;
+ for (i=0; i<FLT_REG_CNT; ++i) {
+ if (nregdescfloat[i] == REG_SAV)
+ frame->nativesavflt[j++] = es->fltregs[i];
+ }
+
+#if defined(HAS_ADDRESS_REGISTER_FILE)
+ j = 0;
+ for (i=0; i<ADR_REG_CNT; ++i) {
+ if (nregdescadr[i] == REG_SAV)
+ frame->nativesavadr[j++] = es->adrregs[i];
+ }
+#endif
+
+ /* restore saved registers */
+
+#if 0
+ /* XXX we don't have them, yet, in the sfi, so clear them */
+
+ for (i=0; i<INT_REG_CNT; ++i) {
+ if (nregdescint[i] == REG_SAV)
+ es->intregs[i] = 0;
+ }
+
+ for (i=0; i<FLT_REG_CNT; ++i) {
+ if (nregdescfloat[i] == REG_SAV)
+ es->fltregs[i] = 0.0;
+ }
+
+# if defined(HAS_ADDRESS_REGISTER_FILE)
+ for (i=0; i<ADR_REG_CNT; ++i) {
+ if (nregdescadr[i] == REG_SAV)
+ es->adrregs[i] = 0;
+ }
+# 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); );
+
+ assert(es->pv != NULL);
+
+ code = *(codeinfo **)(es->pv + CodeinfoPointer);
+
+ DOLOG( printf("CODE = %p\n", (void*) code); );
+
+ es->code = code;
+}
+
+
+/* replace_push_native_frame ***************************************************
+
+ Rebuild a native frame onto the execution state and remove its source frame.
+
+ Note: The native frame is "rebuild" by setting fields like PC and stack
+ pointer in the execution state accordingly. Values in the
+ stackframeinfo may be modified, but the actual stack frame of the
+ native code is not touched.
+
+ IN:
+ es...............current execution state
+ ss...............the current source state
+
+ OUT:
+ es...............execution state after re-rolling the native frame
+ ss...............the native source frame is removed
+
+*******************************************************************************/
+
+static void replace_push_native_frame(executionstate_t *es, sourcestate_t *ss)
+{
+ sourceframe_t *frame;
+ s4 i,j;
+
+ assert(es);
+ assert(ss);
+
+ DOLOG( printf("pushing native frame\n"); );
+
+ /* remove the frame from the source state */
+
+ frame = ss->frames;
+ assert(frame);
+ assert(REPLACE_IS_NATIVE_FRAME(frame));
+
+ ss->frames = frame->down;
+
+ /* assert that the native frame has not moved */
+
+ assert(es->sp == frame->sfi->sp);
+
+ /* restore saved registers */
+
+ j = 0;
+ for (i=0; i<INT_REG_CNT; ++i) {
+ if (nregdescint[i] == REG_SAV)
+ es->intregs[i] = frame->nativesavint[j++];
+ }
+
+ j = 0;
+ for (i=0; i<FLT_REG_CNT; ++i) {
+ if (nregdescfloat[i] == REG_SAV)
+ es->fltregs[i] = frame->nativesavflt[j++];
+ }
+
+#if defined(HAS_ADDRESS_REGISTER_FILE)
+ j = 0;
+ for (i=0; i<ADR_REG_CNT; ++i) {
+ if (nregdescadr[i] == REG_SAV)
+ es->adrregs[i] = frame->nativesavadr[j++];
+ }
+#endif
+
+ /* skip the native frame on the machine stack */
+
+ es->sp -= frame->nativeframesize;
+
+ /* set the pc the next frame must return to */
+
+ es->pc = frame->nativepc;
+}
+
+
/* replace_recover_source_state ************************************************
Recover the source state from the given replacement point and execution
state.
IN:
- rp...............replacement point that has been reached
+ rp...............replacement point that has been reached, if any
+ sfi..............stackframeinfo, if called from native code
es...............execution state at the replacement point rp
RETURN VALUE:
*******************************************************************************/
sourcestate_t *replace_recover_source_state(rplpoint *rp,
+ stackframeinfo *sfi,
executionstate_t *es)
{
sourcestate_t *ss;
u1 *ra;
+ bool locked;
#if defined(REPLACE_STATISTICS)
s4 depth;
#endif
ss = DNEW(sourcestate_t);
ss->frames = NULL;
+ /* get the stackframeinfo if none is given */
+
+ if (sfi == NULL)
+ sfi = STACKFRAMEINFO;
+
/* each iteration of the loop recovers one source frame */
depth = 0;
+ locked = false;
+
+ while (rp || sfi) {
- while (true) {
+ DOLOG( replace_executionstate_println(es); );
+
+ /* if we are not at a replacement point, it is a native frame */
+
+ if (rp == NULL) {
+ DOLOG( printf("native frame: sfi: "); replace_stackframeinfo_println(sfi); );
+
+ locked = true;
+ replace_pop_native_frame(es, ss, sfi);
+ sfi = sfi->prev;
+
+ if (es->code == NULL)
+ continue;
+
+ goto after_machine_frame;
+ }
/* read the values for this source frame from the execution state */
replace_read_executionstate(rp, es, ss, ss->frames == NULL);
+#if defined(ENABLE_VMLOG)
+ vmlog_cacao_unrol_method(ss->frames->method);
+#endif
+
#if defined(REPLACE_STATISTICS)
REPLACE_COUNT(stat_frames);
depth++;
replace_statistics_source_frame(ss->frames);
#endif
+ /* in locked areas (below native frames), identity map the frame */
+
+ if (locked) {
+ ss->frames->torp = ss->frames->fromrp;
+ ss->frames->tocode = ss->frames->fromcode;
+ }
+
/* unroll to the next (outer) frame */
if (rp->parent) {
REPLACE_COUNT(stat_unroll_inline);
}
else {
- /* this frame had been called at machine-level */
+ /* this frame had been called at machine-level. pop it. */
DOLOG( printf("UNWIND\n"); );
ra = replace_pop_activation_record(es, ss->frames);
if (ra == NULL) {
- DOLOG( printf("BREAKING\n"); );
- break;
+ DOLOG( printf("REACHED NATIVE CODE\n"); );
+
+ rp = NULL;
+
+ break; /* XXX remove to activate native frames */
+ continue;
}
+ /* find the replacement point at the call site */
+
+after_machine_frame:
rp = replace_find_replacement_point_for_pc(es->code, es->pc);
if (rp == NULL)
frame, it is (re)compiled.
IN:
- firstcode........XXX temporary hack, will be removed
ss...............the source state
OUT:
*******************************************************************************/
-static bool replace_map_source_state(codeinfo *firstcode, sourcestate_t *ss)
+static bool replace_map_source_state(sourcestate_t *ss)
{
sourceframe_t *frame;
codeinfo *code;
#endif
parent = NULL;
+ code = NULL;
/* iterate over the source frames from outermost to innermost */
- code = firstcode; /* XXX should get code for first frame */
-
- frame = ss->frames;
- while (true) {
+ for (frame = ss->frames; frame != NULL; frame = frame->down) {
- /* map this frame */
+ /* XXX skip native frames */
- rp = replace_find_replacement_point(code, frame, parent);
+ if (REPLACE_IS_NATIVE_FRAME(frame)) {
+ parent = NULL;
+ continue;
+ }
- frame->tocode = code;
- frame->torp = rp;
+ /* map frames which are not already mapped */
- /* go down one frame */
+ if (frame->tocode) {
+ code = frame->tocode;
+ rp = frame->torp;
+ assert(rp);
+ }
+ else {
+ assert(frame->torp == NULL);
- frame = frame->down;
- if (frame == NULL)
- break;
+ if (parent == NULL) {
+ /* find code for this frame */
- if (rp->type == RPLPOINT_TYPE_CALL) {
#if defined(REPLACE_STATISTICS)
- oldcode = frame->method->code;
+ oldcode = frame->method->code;
#endif
- code = jit_get_current_code(frame->method);
+ /* request optimization of hot methods and their callers */
+
+ if (frame->method->hitcountdown < 0
+ || (frame->down && frame->down->method->hitcountdown < 0))
+ jit_request_optimization(frame->method);
+
+ code = jit_get_current_code(frame->method);
+
+ if (code == NULL)
+ return false; /* exception */
- if (code == NULL)
- return false; /* exception */
+ REPLACE_COUNT_IF(stat_recompile, code != oldcode);
+ }
+
+ assert(code);
- REPLACE_COUNT_IF(stat_recompile, code != oldcode);
+ /* map this frame */
+ rp = replace_find_replacement_point(code, frame, parent);
+
+ frame->tocode = code;
+ frame->torp = rp;
+ }
+
+ if (rp->type == RPLPOINT_TYPE_CALL) {
parent = NULL;
}
else {
+ /* inlining */
parent = rp;
}
}
{
rplpoint *rp;
sourceframe_t *prevframe;
+ rplpoint *parent;
- while (true) {
+ parent = NULL;
+ prevframe = NULL;
+ rp = NULL;
- rp = ss->frames->torp;
+ while (ss->frames) {
+
+ if (REPLACE_IS_NATIVE_FRAME(ss->frames)) {
+ prevframe = ss->frames;
+ replace_push_native_frame(es, ss);
+ parent = NULL;
+ rp = NULL;
+ continue;
+ }
+
+ if (parent == NULL) {
+ /* create a machine-level stack frame */
+ DOLOG( printf("pushing activation record for:\n");
+ if (rp) replace_replacement_point_println(rp, 1);
+ else printf("\tfirst frame\n"); );
+
+ replace_push_activation_record(es, rp, prevframe, ss->frames);
+
+ DOLOG( replace_executionstate_println(es); );
+ }
+
+ rp = ss->frames->torp;
assert(rp);
- assert(es->code == ss->frames->tocode);
DOLOG( printf("creating execution state for%s:\n",
(ss->frames->down == NULL) ? " TOPFRAME" : "");
replace_replacement_point_println(ss->frames->fromrp, 1);
replace_replacement_point_println(rp, 1); );
+ es->code = ss->frames->tocode;
prevframe = ss->frames;
- replace_write_executionstate(rp, es, ss, ss->frames->down == NULL);
+#if defined(ENABLE_VMLOG)
+ vmlog_cacao_rerol_method(ss->frames->method);
+#endif
- if (ss->frames == NULL)
- break;
+ replace_write_executionstate(rp, es, ss, ss->frames->down == NULL);
DOLOG( replace_executionstate_println(es); );
if (rp->type == RPLPOINT_TYPE_CALL) {
-
- DOLOG( printf("pushing activation record for:\n");
- replace_replacement_point_println(rp, 1); );
-
- replace_push_activation_record(es, rp, prevframe, ss->frames);
+ parent = NULL;
+ }
+ else {
+ /* inlining */
+ parent = rp;
}
-
- DOLOG( replace_executionstate_println(es); );
}
}
}
+/* replace_me_wrapper **********************************************************
+
+ TODO: Document me!
+
+*******************************************************************************/
+
+bool replace_me_wrapper(u1 *pc)
+{
+ 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 */
+
+#if 0
+ rp = replace_find_replacement_point_for_pc(code, pc);
+ assert(rp == NULL || rp->pc == pc);
+#else
+ {
+ int i;
+ rplpoint *rp2;
+ rp = NULL;
+ for (i=0,rp2=code->rplpoints; i<code->rplpointcount; i++,rp2++) {
+ if (rp2->pc == pc)
+ rp = rp2;
+ }
+ }
+#endif
+
+ /* check if the replacement point is active */
+
+ if (rp != NULL && (rp->flags & RPLPOINT_FLAG_ACTIVE)) {
+
+ /*md_replace_executionstate_read(&es, context);*/
+
+ replace_me(rp, &es);
+
+ return true;
+ }
+ else
+ return false;
+}
+
+
/* replace_me ******************************************************************
This function is called by asm_replacement_out when a thread reaches
/* recover source state */
- ss = replace_recover_source_state(rp, es);
+ ss = replace_recover_source_state(rp, NULL, es);
/* map the source state */
- if (!replace_map_source_state(es->code, ss))
+ if (!replace_map_source_state(ss))
vm_abort("exception during method replacement");
DOLOG( replace_sourcestate_println(ss); );
/* call the assembler code for the last phase of replacement */
-#if (defined(__I386__) || defined(__X86_64__) || defined(__ALPHA__) || defined(__POWERPC__) || defined(__MIPS__)) && defined(ENABLE_JIT)
- asm_replacement_in(&(safestack->es), safestack);
+#if (defined(__I386__) || defined(__X86_64__) || defined(__ALPHA__) || defined(__POWERPC__) || defined(__MIPS__) || defined(__S390__)) && defined(ENABLE_JIT)
+ /*asm_replacement_in(&(safestack->es), safestack);*/
#endif
abort(); /* NOT REACHED */
replace_type_str[rp->type]);
if (rp->flags & RPLPOINT_FLAG_NOTRAP)
printf(" NOTRAP");
+ if (rp->flags & RPLPOINT_FLAG_COUNTDOWN)
+ printf(" COUNTDOWN");
if (rp->flags & RPLPOINT_FLAG_ACTIVE)
printf(" ACTIVE");
printf(" parent:%p\n", (void*)rp->parent);
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");
else
printf(" ");
#if SIZEOF_VOID_P == 8
- printf("%-3s = %016llx",regs[i],(unsigned long long)es->intregs[i]);
+ printf("%-3s = %016llx",abi_registers_integer_name[i],(unsigned long long)es->intregs[i]);
#else
- printf("%-3s = %08lx",regs[i],(unsigned long)es->intregs[i]);
+ printf("%-3s = %08lx",abi_registers_integer_name[i],(unsigned long)es->intregs[i]);
#endif
if (i%4 == 3)
printf("\n");
if (i%4 == 3)
printf("\n");
}
+# if defined(HAS_ADDRESS_REGISTER_FILE)
+ for (i=0; i<ADR_REG_CNT; ++i) {
+ if (i%4 == 0)
+ printf("\t");
+ else
+ printf(" ");
+ printf("A%02d = %016llx",i,(unsigned long long)es->adrregs[i]);
+ if (i%4 == 3)
+ printf("\n");
+ }
+# endif
#endif
sp = (stackslot_t *) es->sp;
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
#endif
#if !defined(NDEBUG)
-static void java_value_print(s4 type, u8 value)
+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);
+ printf("%016llx",(unsigned long long) value.l);
if (type < 0 || type > TYPE_RET)
printf(" <INVALID TYPE:%d>", type);
else
printf(" %s", show_jit_type_names[type]);
- if (type == TYPE_ADR && value != 0) {
- obj = (java_objectheader *) (ptrint) value;
+ if (type == TYPE_ADR && value.a != NULL) {
+ obj = value.a;
putchar(' ');
utf_display_printable_ascii_classname(obj->vftbl->class->name);
if (obj->vftbl->class == class_java_lang_String) {
printf(" \"");
- u = javastring_toutf((java_lang_String *)obj, false);
+ u = javastring_toutf(obj, false);
utf_display_printable_ascii(u);
printf("\"");
}
}
- else if (type == TYPE_INT || type == TYPE_LNG) {
- printf(" %lld", (long long) value);
+ else if (type == TYPE_INT) {
+ printf(" %ld", (long) value.i);
+ }
+ else if (type == TYPE_LNG) {
+ printf(" %lld", (long long) value.l);
+ }
+ else if (type == TYPE_FLT) {
+ printf(" %f", value.f);
+ }
+ else if (type == TYPE_DBL) {
+ printf(" %f", value.d);
}
}
#endif /* !defined(NDEBUG) */
#if !defined(NDEBUG)
void replace_source_frame_println(sourceframe_t *frame)
{
- s4 i;
+ s4 i,j;
s4 t;
+ if (REPLACE_IS_NATIVE_FRAME(frame)) {
+ printf("\tNATIVE\n");
+ printf("\tsfi: "); replace_stackframeinfo_println(frame->sfi);
+ printf("\tnativepc: %p\n", frame->nativepc);
+ printf("\tframesize: %d\n", frame->nativeframesize);
+
+ j = 0;
+ for (i=0; i<INT_REG_CNT; ++i) {
+ if (nregdescint[i] == REG_SAV)
+ printf("\t%s = %p\n", abi_registers_integer_name[i], (void*)frame->nativesavint[j++]);
+ }
+
+ j = 0;
+ for (i=0; i<FLT_REG_CNT; ++i) {
+ if (nregdescfloat[i] == REG_SAV)
+ printf("\tF%02d = %f\n", i, frame->nativesavflt[j++]);
+ }
+
+ printf("\n");
+ return;
+ }
+
printf("\t");
method_println(frame->method);
printf("\tid: %d\n", frame->id);
printf("\ttype: %s\n", replace_type_str[frame->type]);
printf("\n");
- if (frame->instance) {
+ if (frame->instance.a) {
printf("\tinstance: ");
java_value_print(TYPE_ADR, frame->instance);
printf("\n");
for (i=0; i<frame->syncslotcount; ++i) {
printf("\tslot[%2d] = ",i);
#ifdef HAS_4BYTE_STACKSLOT
- printf("%08lx\n",(unsigned long) frame->syncslots[i]);
+ printf("%08lx\n",(unsigned long) frame->syncslots[i].p);
#else
- printf("%016llx\n",(unsigned long long) frame->syncslots[i]);
+ printf("%016llx\n",(unsigned long long) frame->syncslots[i].p);
#endif
}
printf("\n");
for (frame = ss->frames; frame != NULL; frame = frame->down) {
printf("\t");
+ if (REPLACE_IS_NATIVE_FRAME(frame)) {
+ printf("NATIVE (pc %p size %d) ",
+ (void*)frame->nativepc, frame->nativeframesize);
+ replace_stackframeinfo_println(frame->sfi);
+ continue;
+ }
+
if (frame->torp) {
printf("%c", (frame->torp == frame->fromrp) ? '=' : '+');
}
}
#endif
+#if !defined(NDEBUG)
+static void replace_stackframeinfo_println(stackframeinfo *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);
+ else
+ printf("(nil)\n");
+}
+#endif
+
/*
* These are local overrides for various environment variables in Emacs.
* Please do not remove this and leave it at the end of the file, where