Unified variables changes for common/i386.
[cacao.git] / src / vm / jit / replace.c
index bb4365a4cfa7e7954769bf28346f91a352dad116..060203db71d5ee67c3870b24cefaa52b7ab30105 100644 (file)
 #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;
@@ -83,6 +99,11 @@ bool replace_create_replacement_points(codeinfo *code,registerdata *rd)
        stackptr sp;
        bool indexused;
 
+       /* get required compiler data */
+
+       code = jd->code;
+       rd   = jd->rd;
+
        /* assert that we wont overwrite already allocated data */
        
        assert(code);
@@ -99,7 +120,8 @@ bool replace_create_replacement_points(codeinfo *code,registerdata *rd)
 
        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;
 
@@ -177,7 +199,8 @@ bool replace_create_replacement_points(codeinfo *code,registerdata *rd)
        /* 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;
 
@@ -185,10 +208,11 @@ bool replace_create_replacement_points(codeinfo *code,registerdata *rd)
 
                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 */
 
@@ -207,18 +231,19 @@ bool replace_create_replacement_points(codeinfo *code,registerdata *rd)
 
        /* 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 *********************************************
@@ -271,7 +296,7 @@ void replace_activate_replacement_point(rplpoint *rp,rplpoint *target)
        
        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
 }
@@ -299,11 +324,91 @@ void replace_deactivate_replacement_point(rplpoint *rp)
        
        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)
 {
@@ -314,19 +419,55 @@ static void replace_read_executionstate(rplpoint *rp,executionstate *es,
        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;
@@ -337,7 +478,14 @@ static void replace_read_executionstate(rplpoint *rp,executionstate *es,
        /* 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;
 
@@ -349,12 +497,7 @@ static void replace_read_executionstate(rplpoint *rp,executionstate *es,
                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 */
@@ -363,17 +506,40 @@ static void replace_read_executionstate(rplpoint *rp,executionstate *es,
        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 */
@@ -382,7 +548,7 @@ static void replace_read_executionstate(rplpoint *rp,executionstate *es,
        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 */
@@ -391,20 +557,53 @@ static void replace_read_executionstate(rplpoint *rp,executionstate *es,
                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;
@@ -413,21 +612,49 @@ static void replace_write_executionstate(rplpoint *rp,executionstate *es,sources
        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 */
 
@@ -454,12 +681,7 @@ static void replace_write_executionstate(rplpoint *rp,executionstate *es,sources
                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 */
@@ -468,15 +690,32 @@ static void replace_write_executionstate(rplpoint *rp,executionstate *es,sources
 
        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 */
@@ -485,7 +724,7 @@ static void replace_write_executionstate(rplpoint *rp,executionstate *es,sources
        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 */
@@ -494,12 +733,37 @@ static void replace_write_executionstate(rplpoint *rp,executionstate *es,sources
                *--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 ******************************************************************
@@ -529,6 +793,10 @@ void replace_me(rplpoint *rp,executionstate *es)
        /* 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);
@@ -548,7 +816,6 @@ void replace_me(rplpoint *rp,executionstate *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);
@@ -560,7 +827,7 @@ void replace_me(rplpoint *rp,executionstate *es)
 
        /* 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();
@@ -589,9 +856,9 @@ void replace_replacement_point_println(rplpoint *rp)
                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",
@@ -600,7 +867,7 @@ void replace_replacement_point_println(rplpoint *rp)
                                rp->regalloc[j].flags,
                                rp->regalloc[j].index);
 
-       printf("] method:");
+       printf("]\n          method: ");
        method_print(rp->code->m);
 
        printf("\n");
@@ -671,8 +938,12 @@ void replace_show_replacement_points(codeinfo *code)
 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");
@@ -682,11 +953,21 @@ void replace_executionstate_println(executionstate *es,codeinfo *code)
        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);
@@ -695,7 +976,11 @@ void replace_executionstate_println(executionstate *es,codeinfo *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");
@@ -716,13 +1001,14 @@ void replace_sourcestate_println(sourcestate *ss)
 {
        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) {
@@ -745,9 +1031,14 @@ void replace_sourcestate_println(sourcestate *ss)
        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]);
                }
        }
@@ -763,6 +1054,18 @@ void replace_sourcestate_println(sourcestate *ss)
        }
        
        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