#include <assert.h>
#include <stdlib.h>
+#include "arch.h"
+
#include "mm/memory.h"
+#include "toolbox/logging.h"
#include "vm/options.h"
+#include "vm/jit/abi.h"
+#include "vm/jit/jit.h"
#include "vm/jit/replace.h"
#include "vm/jit/asmpart.h"
+#include "vm/jit/disass.h"
+
+
+/*** constants used internally ************************************************/
+
+#define TOP_IS_NORMAL 0
+#define TOP_IS_ON_STACK 1
+#define TOP_IS_IN_ITMP1 2
/* replace_create_replacement_points *******************************************
*******************************************************************************/
-bool replace_create_replacement_points(codeinfo *code,registerdata *rd)
+bool replace_create_replacement_points(jitdata *jd)
{
+#if 0
+ codeinfo *code;
+ registerdata *rd;
basicblock *bptr;
int count;
methodinfo *m;
stackptr sp;
bool indexused;
+ /* get required compiler data */
+
+ code = jd->code;
+ rd = jd->rd;
+
/* assert that we wont overwrite already allocated data */
assert(code);
count = 0;
alloccount = 0;
- for (bptr = m->basicblocks; bptr; bptr = bptr->next) {
+
+ for (bptr = jd->new_basicblocks; bptr; bptr = bptr->next) {
if (!(bptr->bitflags & BBFLAG_REPLACEMENT))
continue;
/* initialize replacement point structs */
rp = rplpoints;
- for (bptr = m->basicblocks; bptr; bptr = bptr->next) {
+
+ for (bptr = jd->new_basicblocks; bptr; bptr = bptr->next) {
if (!(bptr->bitflags & BBFLAG_REPLACEMENT))
continue;
rp->pc = NULL; /* set by codegen */
rp->outcode = NULL; /* set by codegen */
- rp->hashlink = NULL;
rp->code = code;
rp->target = NULL;
rp->regalloc = ra;
+ rp->flags = 0;
+ rp->type = bptr->type;
/* store local allocation info */
/* store the data in the codeinfo */
- code->rplpoints = rplpoints;
+ code->rplpoints = rplpoints;
code->rplpointcount = count;
- code->regalloc = regalloc;
+ code->regalloc = regalloc;
code->regalloccount = alloccount;
- code->globalcount = globalcount;
+ code->globalcount = globalcount;
code->savedintcount = INT_SAV_CNT - rd->savintreguse;
code->savedfltcount = FLT_SAV_CNT - rd->savfltreguse;
- code->memuse = rd->memuse;
+ code->memuse = rd->memuse;
/* everything alright */
return true;
+#endif
}
/* replace_free_replacement_points *********************************************
rp->target = target;
-#if defined(__I386__) && defined(ENABLE_JIT)
+#if (defined(__I386__) || defined(__X86_64__) || defined(__ALPHA__) || defined(__POWERPC__) || defined(__MIPS__)) && defined(ENABLE_JIT)
md_patch_replacement_point(rp);
#endif
}
rp->target = NULL;
-#if defined(__I386__) && defined(ENABLE_JIT)
+#if (defined(__I386__) || defined(__X86_64__) || defined(__ALPHA__) || defined(__POWERPC__) || defined(__MIPS__)) && defined(ENABLE_JIT)
md_patch_replacement_point(rp);
#endif
}
+/* replace_read_executionstate *************************************************
+
+ Read the given executions state and translate it to a source state.
+
+ IN:
+ rp...............replacement point at which `es` was taken
+ es...............execution state
+ ss...............where to put the source state
+
+ OUT:
+ *ss..............the source state derived from the execution state
+
+*******************************************************************************/
+
+inline static void replace_read_value(executionstate *es,
+#ifdef HAS_4BYTE_STACKSLOT
+ u4 *sp,
+#else
+ u8 *sp,
+#endif
+ rplalloc *ra,
+ u8 *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->index);
+ }
+ else {
+#endif
+ *javaval = sp[ra->index];
+#ifdef HAS_4BYTE_STACKSLOT
+ }
+#endif
+ }
+ else {
+ /* allocated register */
+ if (IS_FLT_DBL_TYPE(ra->type)) {
+ *javaval = es->fltregs[ra->index];
+ }
+ else {
+ *javaval = es->intregs[ra->index];
+ }
+ }
+}
+
+inline static void replace_write_value(executionstate *es,
+#ifdef HAS_4BYTE_STACKSLOT
+ u4 *sp,
+#else
+ u8 *sp,
+#endif
+ rplalloc *ra,
+ u8 *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->index) = *javaval;
+ }
+ else {
+#endif
+ sp[ra->index] = *javaval;
+#ifdef HAS_4BYTE_STACKSLOT
+ }
+#endif
+ }
+ else {
+ /* allocated register */
+ if (IS_FLT_DBL_TYPE(ra->type)) {
+ es->fltregs[ra->index] = *javaval;
+ }
+ else {
+ es->intregs[ra->index] = *javaval;
+ }
+ }
+}
+
static void replace_read_executionstate(rplpoint *rp,executionstate *es,
sourcestate *ss)
{
int t;
int allocs;
rplalloc *ra;
- u4 *sp; /* XXX configure stack slot size */
- u4 *basesp;
methoddesc *md;
+ int topslot;
+#ifdef HAS_4BYTE_STACKSLOT
+ u4 *sp;
+ u4 *basesp;
+#else
+ u8 *sp;
+ u8 *basesp;
+#endif
code = rp->code;
m = code->m;
md = m->parseddesc;
+ topslot = TOP_IS_NORMAL;
- /* calculate stack pointers */
+ /* stack pointers */
+#ifdef HAS_4BYTE_STACKSLOT
sp = (u4*) es->sp;
+#else
+ sp = (u8*) es->sp;
+#endif
+
+ /* on some architectures the returnAddress is passed on the stack by JSR */
+
+#if defined(__I386__) || defined(__X86_64__)
+ if (rp->type == BBTYPE_SBR) {
+ sp++;
+ topslot = TOP_IS_ON_STACK;
+ }
+#endif
+
+ /* in some cases the top stack slot is passed in REG_ITMP1 */
+
+ if ( (rp->type == BBTYPE_EXH)
+#if defined(__ALPHA__) || defined(__POWERPC__) || defined(__MIPS__)
+ || (rp->type == BBTYPE_SBR)
+#endif
+ )
+ {
+ topslot = TOP_IS_IN_ITMP1;
+ }
+
+ /* calculate base stack pointer */
+
basesp = sp + code_get_stack_frame_size(code);
+ ss->stackbase = (u1*) basesp;
+
/* read local variables */
count = m->maxlocals;
/* mark values as undefined */
for (i=0; i<count*5; ++i)
ss->javalocals[i] = (u8) 0x00dead0000dead00ULL;
+
+ /* some entries in the intregs array are not meaningful */
+ /*es->intregs[REG_ITMP3] = (u8) 0x11dead1111dead11ULL;*/
+ es->intregs[REG_SP ] = (u8) 0x11dead1111dead11ULL;
+#ifdef REG_PV
+ es->intregs[REG_PV ] = (u8) 0x11dead1111dead11ULL;
#endif
+#endif /* NDEBUG */
ra = code->regalloc;
if (t == -1)
continue; /* dummy rplalloc */
- if (ra->flags & INMEMORY) {
- ss->javalocals[i*5+t] = sp[ra->index];
- }
- else {
- ss->javalocals[i*5+t] = es->regs[ra->index];
- }
+ replace_read_value(es,sp,ra,ss->javalocals + (5*i+t));
}
/* read stack slots */
ss->javastackdepth = count;
ss->javastack = DMNEW(u8,count);
+#ifndef NDEBUG
+ /* mark values as undefined */
+ for (i=0; i<count; ++i)
+ ss->javastack[i] = (u8) 0x00dead0000dead00ULL;
+#endif
+
i = 0;
ra = rp->regalloc;
+
+ /* the first stack slot is special in SBR and EXH blocks */
+
+ if (topslot == TOP_IS_ON_STACK) {
+ assert(count);
+
+ ss->javastack[i] = sp[-1];
+ count--;
+ i++;
+ ra++;
+ }
+ else if (topslot == TOP_IS_IN_ITMP1) {
+ assert(count);
+
+ ss->javastack[i] = es->intregs[REG_ITMP1];
+ count--;
+ i++;
+ ra++;
+ }
+
+ /* read remaining stack slots */
+
for (; count--; ra++, i++) {
assert(ra->next);
- if (ra->flags & INMEMORY) {
- ss->javastack[i] = sp[ra->index];
- }
- else {
- ss->javastack[i] = es->regs[ra->index];
- }
+ replace_read_value(es,sp,ra,ss->javastack + i);
}
/* read unused callee saved int regs */
for (i=0; count > code->savedintcount; ++i) {
assert(i < INT_REG_CNT);
if (nregdescint[i] == REG_SAV)
- ss->savedintregs[--count] = es->regs[i];
+ ss->savedintregs[--count] = es->intregs[i];
}
/* read saved int regs */
ss->savedintregs[i] = *--basesp;
}
+ /* read unused callee saved flt regs */
+
+ count = FLT_SAV_CNT;
+ for (i=0; count > code->savedfltcount; ++i) {
+ assert(i < FLT_REG_CNT);
+ if (nregdescfloat[i] == REG_SAV)
+ ss->savedfltregs[--count] = es->fltregs[i];
+ }
+
/* read saved flt regs */
for (i=0; i<code->savedfltcount; ++i) {
+#ifdef HAS_4BYTE_STACKSLOT
basesp -= 2;
+#else
+ basesp--;
+#endif
ss->savedfltregs[i] = *(u8*)basesp;
}
-#ifndef NDEBUG
- /* XXX */
- for (; i<FLT_SAV_CNT; ++i)
- ss->savedfltregs[i] = (u8) 0x00dead0000dead00ULL;
-#endif
+
+ /* read slots used for synchronization */
+
+ count = code_get_sync_slot_count(code);
+ ss->syncslotcount = count;
+ ss->syncslots = DMNEW(u8,count);
+ for (i=0; i<count; ++i) {
+ ss->syncslots[i] = sp[code->memuse + i];
+ }
}
-static void replace_write_executionstate(rplpoint *rp,executionstate *es,sourcestate *ss)
+/* replace_write_executionstate ************************************************
+
+ Translate the given source state into an execution state.
+
+ IN:
+ rp...............replacement point for which execution state should be
+ creates
+ es...............where to put the execution state
+ ss...............the given source state
+
+ OUT:
+ *es..............the execution state derived from the source state
+
+*******************************************************************************/
+
+static void replace_write_executionstate(rplpoint *rp,executionstate *es,
+ sourcestate *ss)
{
methodinfo *m;
codeinfo *code;
int t;
int allocs;
rplalloc *ra;
- u4 *sp; /* XXX configure stack slot size */
- u4 *basesp; /* XXX configure stack slot size */
methoddesc *md;
+ int topslot;
+#ifdef HAS_4BYTE_STACKSLOT
+ u4 *sp;
+ u4 *basesp;
+#else
+ u8 *sp;
+ u8 *basesp;
+#endif
code = rp->code;
m = code->m;
md = m->parseddesc;
+ topslot = TOP_IS_NORMAL;
+
+ /* calculate stack pointer */
+
+#ifdef HAS_4BYTE_STACKSLOT
+ basesp = (u4*) ss->stackbase;
+#else
+ basesp = (u8*) ss->stackbase;
+#endif
- /* calculate stack pointers */
+ sp = basesp - code_get_stack_frame_size(code);
- sp = (u4*) es->sp;
- basesp = sp + code_get_stack_frame_size(code);
+ /* on some architectures the returnAddress is passed on the stack by JSR */
- if (checksync && (m->flags & ACC_SYNCHRONIZED))
- basesp += (IS_2_WORD_TYPE(md->returntype.type)) ? 2 : 1;
+#if defined(__I386__) || defined(__X86_64__)
+ if (rp->type == BBTYPE_SBR) {
+ topslot = TOP_IS_ON_STACK;
+ }
+#endif
+
+ /* in some cases the top stack slot is passed in REG_ITMP1 */
+
+ if ( (rp->type == BBTYPE_EXH)
+#if defined(__ALPHA__) || defined(__POWERPC__) || defined(__MIPS__)
+ || (rp->type == BBTYPE_SBR)
+#endif
+ )
+ {
+ topslot = TOP_IS_IN_ITMP1;
+ }
/* in debug mode, invalidate stack frame first */
if (t == -1)
continue; /* dummy rplalloc */
- if (ra->flags & INMEMORY) {
- sp[ra->index] = ss->javalocals[i*5+t];
- }
- else {
- es->regs[ra->index] = ss->javalocals[i*5+t];
- }
+ replace_write_value(es,sp,ra,ss->javalocals + (5*i+t));
}
/* write stack slots */
i = 0;
ra = rp->regalloc;
+
+ /* the first stack slot is special in SBR and EXH blocks */
+
+ if (topslot == TOP_IS_ON_STACK) {
+ assert(count);
+
+ sp[-1] = ss->javastack[i];
+ count--;
+ i++;
+ ra++;
+ }
+ else if (topslot == TOP_IS_IN_ITMP1) {
+ assert(count);
+
+ es->intregs[REG_ITMP1] = ss->javastack[i];
+ count--;
+ i++;
+ ra++;
+ }
+
+ /* write remaining stack slots */
+
for (; count--; ra++, i++) {
assert(ra->next);
- if (ra->flags & INMEMORY) {
- sp[ra->index] = ss->javastack[i];
- }
- else {
- es->regs[ra->index] = ss->javastack[i];
- }
+ replace_write_value(es,sp,ra,ss->javastack + i);
}
/* write unused callee saved int regs */
for (i=0; count > code->savedintcount; ++i) {
assert(i < INT_REG_CNT);
if (nregdescint[i] == REG_SAV)
- es->regs[i] = ss->savedintregs[--count];
+ es->intregs[i] = ss->savedintregs[--count];
}
/* write saved int regs */
*--basesp = ss->savedintregs[i];
}
+ /* write unused callee saved flt regs */
+
+ count = FLT_SAV_CNT;
+ for (i=0; count > code->savedfltcount; ++i) {
+ assert(i < FLT_REG_CNT);
+ if (nregdescfloat[i] == REG_SAV)
+ es->fltregs[i] = ss->savedfltregs[--count];
+ }
+
/* write saved flt regs */
for (i=0; i<code->savedfltcount; ++i) {
+#ifdef HAS_4BYTE_STACKSLOT
basesp -= 2;
+#else
+ basesp--;
+#endif
*(u8*)basesp = ss->savedfltregs[i];
}
+
+ /* write slots used for synchronization */
+
+ count = code_get_sync_slot_count(code);
+ assert(count == ss->syncslotcount);
+ for (i=0; i<count; ++i) {
+ sp[code->memuse + i] = ss->syncslots[i];
+ }
+
+ /* set new pc */
+
+ es->pc = rp->pc;
}
/* replace_me ******************************************************************
/* fetch the target of the replacement */
target = rp->target;
+
+ /* XXX DEBUG turn off self-replacement */
+ if (target == rp)
+ replace_deactivate_replacement_point(rp);
#ifndef NDEBUG
printf("replace_me(%p,%p)\n",(void*)rp,(void*)es);
/* write execution state of new code */
replace_write_executionstate(target,es,&ss);
- es->pc = rp->target->pc;
#ifndef NDEBUG
replace_executionstate_println(es,target->code);
/* enter new code */
-#if defined(__I386__) && defined(ENABLE_JIT)
+#if (defined(__I386__) || defined(__X86_64__) || defined(__ALPHA__) || defined(__POWERPC__) || defined(__MIPS__)) && defined(ENABLE_JIT)
asm_replacement_in(es);
#endif
abort();
return;
}
- printf("rplpoint %p pc:%p out:%p target:%p mcode:%016llx allocs:%d = [",
+ printf("rplpoint %p pc:%p out:%p target:%p mcode:%016llx type:%01d flags:%01x ra:%d = [",
(void*)rp,rp->pc,rp->outcode,(void*)rp->target,
- (unsigned long long)rp->mcode,rp->regalloccount);
+ (unsigned long long)rp->mcode,rp->type,rp->flags,rp->regalloccount);
for (j=0; j<rp->regalloccount; ++j)
printf("%c%1c%01x:%02d",
rp->regalloc[j].flags,
rp->regalloc[j].index);
- printf("] method:");
+ printf("]\n method: ");
method_print(rp->code->m);
printf("\n");
void replace_executionstate_println(executionstate *es,codeinfo *code)
{
int i;
- u4 *slotptr; /* XXX configure stack slot size */
int slots;
+#ifdef HAS_4BYTE_STACKSLOT
+ u4 *sp;
+#else
+ u8 *sp;
+#endif
if (!es) {
printf("(executionstate *)NULL\n");
printf("executionstate %p:\n",(void*)es);
printf("\tpc = %p\n",(void*)es->pc);
printf("\tsp = %p\n",(void*)es->sp);
- for (i=0; i<MD_EXCSTATE_NREGS; ++i) {
- printf("\tregs[%2d] = %016llx\n",i,(unsigned long long)es->regs[i]);
+ printf("\tpv = %p\n",(void*)es->pv);
+#if defined(ENABLE_DISASSEMBLER)
+ for (i=0; i<INT_REG_CNT; ++i) {
+ printf("\t%-3s = %016llx\n",regs[i],(unsigned long long)es->intregs[i]);
}
+ for (i=0; i<FLT_REG_CNT; ++i) {
+ printf("\tfltregs[%2d] = %016llx\n",i,(unsigned long long)es->fltregs[i]);
+ }
+#endif
- slotptr = (u4*) es->sp;
+#ifdef HAS_4BYTE_STACKSLOT
+ sp = (u4*) es->sp;
+#else
+ sp = (u8*) es->sp;
+#endif
if (code)
slots = code_get_stack_frame_size(code);
printf("\tstack slots at sp:\n");
for (i=0; i<slots; ++i) {
- printf("\t\t%08lx\n",(unsigned long)*slotptr++);
+#ifdef HAS_4BYTE_STACKSLOT
+ printf("\t\t%08lx\n",(unsigned long)*sp++);
+#else
+ printf("\t\t%016llx\n",(unsigned long long)*sp++);
+#endif
}
printf("\n");
{
int i;
int t;
+ int reg;
if (!ss) {
printf("(sourcestate *)NULL\n");
return;
}
- printf("sourcestate %p:\n",(void*)ss);
+ printf("sourcestate %p: stackbase=%p\n",(void*)ss,(void*)ss->stackbase);
printf("\tlocals (%d):\n",ss->javalocalcount);
for (i=0; i<ss->javalocalcount; ++i) {
printf("\n");
printf("\tsaved int registers (%d):\n",INT_SAV_CNT);
+ reg = INT_REG_CNT;
for (i=0; i<INT_SAV_CNT; ++i) {
+ while (nregdescint[--reg] != REG_SAV)
+ ;
if (ss->savedintregs[i] != 0x00dead0000dead00ULL) {
- printf("\tsavedintreg[%2d] = ",i);
+#if defined(ENABLE_DISASSEMBLER)
+ printf("\t%-3s = ",regs[reg]);
+#endif
printf("%016llx\n",(unsigned long long) ss->savedintregs[i]);
}
}
}
printf("\n");
+
+ printf("\tsynchronization slots (%d):\n",ss->syncslotcount);
+ for (i=0; i<ss->syncslotcount; ++i) {
+ printf("\tslot[%2d] = ",i);
+#ifdef HAS_4BYTE_STACKSLOT
+ printf("%08lx\n",(unsigned long) ss->syncslots[i]);
+#else
+ printf("%016llx\n",(unsigned long long) ss->syncslots[i]);
+#endif
+ }
+
+ printf("\n");
}
#endif