132 lines · 1.9 KB · C
RawDownload
#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;}