#include "java.h" /* * Patch operands, etc. that reference pc offsets. */ enum { P_CASE = 1, P_OTHER}; typedef struct Patch Patch; struct Patch { uchar kind; /* P_xxx */ Inst *i; int n; /* number of cases in ... */ int *jmptbl; /* ... case jump table */ Patch *next;}; static Patch *plist; /* * Allocate a Patch structure. */ static Patch*newPatch(uchar kind, Inst *i){ Patch *p; p = Malloc(sizeof(Patch)); p->kind = kind; p->i = i; p->next = plist; plist = p; return p;} /* * Record non-case branch instruction for later patching. */ voidpatchop(Inst *i){ newPatch(P_OTHER, i);} /* * Record case jump table for later patching. */ voidpatchcase(Inst *i, int n, int *jmptbl){ Patch *p; p = newPatch(P_CASE, i); p->n = n; p->jmptbl = jmptbl;} /* * Calculate patch address; Java branches are relative. */ static intpatchaddr(Inst *i, int pc){ Jinst *j; int span, srcjpc, dstjpc; span = pc; srcjpc = i->j->pc; dstjpc = srcjpc + span; j = &code->j[dstjpc]; /* account for no-op's (dup, swap, pop, etc.), elided loads/stores */ while(j->dis == nil) j += j->size; return j->dis->pc;} /* * Patch branch instructions and case jump tables of a method. */ voidpatchmethod(int startpc){ Patch *p; Inst *i; int *jt; int n; for(p = plist; p; p = p->next) { i = p->i; if(p->kind == P_CASE) { jt = p->jmptbl; for(n = 0; n < p->n; n++) jt[n*3+2] = patchaddr(i, jt[n*3+2]); jt[p->n*3] = patchaddr(i, jt[p->n*3]); } else { /* P_OTHER */ i->d.u.ival = patchaddr(i, i->d.u.ival); /* * jmp $start_of_method -> jmp $start_of_method+1 * skip (re-)allocation of Sys->Exception object */ if(i->d.u.ival == startpc && i->op == IJMP && code->nex != 0) i->d.u.ival += 1; } }} /* * Clear the patch list after each method. */ voidpatchfree(void){ Patch *p, *p2; for(p = plist; p; p = p2) { p2 = p->next; free(p); } plist = nil;}
#include "java.h"
/*
* Patch operands, etc. that reference pc offsets.
*/
enum {
P_CASE = 1,
P_OTHER
};
typedef struct Patch Patch;
struct Patch {
uchar kind; /* P_xxx */
Inst *i;
int n; /* number of cases in ... */
int *jmptbl; /* ... case jump table */
Patch *next;
};
static Patch *plist;
/*
* Allocate a Patch structure.
*/
static Patch*
newPatch(uchar kind, Inst *i)
{
Patch *p;
p = Malloc(sizeof(Patch));
p->kind = kind;
p->i = i;
p->next = plist;
plist = p;
return p;
}
/*
* Record non-case branch instruction for later patching.
*/
void
patchop(Inst *i)
{
newPatch(P_OTHER, i);
}
/*
* Record case jump table for later patching.
*/
void
patchcase(Inst *i, int n, int *jmptbl)
{
Patch *p;
p = newPatch(P_CASE, i);
p->n = n;
p->jmptbl = jmptbl;
}
/*
* Calculate patch address; Java branches are relative.
*/
static int
patchaddr(Inst *i, int pc)
{
Jinst *j;
int span, srcjpc, dstjpc;
span = pc;
srcjpc = i->j->pc;
dstjpc = srcjpc + span;
j = &code->j[dstjpc];
/* account for no-op's (dup, swap, pop, etc.), elided loads/stores */
while(j->dis == nil)
j += j->size;
return j->dis->pc;
}
/*
* Patch branch instructions and case jump tables of a method.
*/
void
patchmethod(int startpc)
{
Patch *p;
Inst *i;
int *jt;
int n;
for(p = plist; p; p = p->next) {
i = p->i;
if(p->kind == P_CASE) {
jt = p->jmptbl;
for(n = 0; n < p->n; n++)
jt[n*3+2] = patchaddr(i, jt[n*3+2]);
jt[p->n*3] = patchaddr(i, jt[p->n*3]);
} else { /* P_OTHER */
i->d.u.ival = patchaddr(i, i->d.u.ival);
/*
* jmp $start_of_method -> jmp $start_of_method+1
* skip (re-)allocation of Sys->Exception object
*/
if(i->d.u.ival == startpc && i->op == IJMP && code->nex != 0)
i->d.u.ival += 1;
}
}
}
/*
* Clear the patch list after each method.
*/
void
patchfree(void)
{
Patch *p, *p2;
for(p = plist; p; p = p2) {
p2 = p->next;
free(p);
}
plist = nil;
}