514 lines · 8.7 KB · C
RawDownload
#include "java.h"#include "javaisa.h" /* * Manage method frame. */ /* * Local variables (including function parameters). */ typedef struct Local	Local; struct Local {			/* local variable */	uchar	dtype;		/* type of local (DIS_[BWLP]) */	int	offset;		/* fp offset of this local */	Local	*next;		/* for locals that are reused */}; static	int	frameoff;	/* tracks growth of frame */static	int	maxframe;	/* size of largest frame */static	Local	*locals;	/* local variables */static	int	nlocals;	/* number of locals (in the Java sense) */ /* * fp temporaries. */ typedef struct Fp	Fp; struct Fp {	uchar	dtype;	int	refcnt;}; static	int	tmpslwm;	/* lowest temporary fp offset */static	int	tmpssz;		/* size of tmps array */static	Fp	*tmps;		/* temporary arena */ /* * Resize the locals array. * * Since the Java VM reuses local variables (e.g., perhaps using * the same slot for an int and an Object reference), max_locals * doesn't always give the number of Dis locals to allow for. */ static voidresizelocals(int ix){	int oldsz; 	oldsz = nlocals;	while(ix >= nlocals)		nlocals += ALLOCINCR;	locals = Realloc(locals, nlocals*sizeof(Local));	memset(&locals[oldsz], 0, ALLOCINCR*sizeof(Local));} /* * Reserve a frame cell for a local variable of the given type. * The Java VM reuses local variables. */ static voidreservelocal(uchar dtype, int ix){	Local *l; 	if(ix >= nlocals)		resizelocals(ix);	if(locals[ix].dtype == dtype)		return;	if(locals[ix].dtype == DIS_X)	/* not yet reserved */		l = &locals[ix];	else {				/* check reuse list */		for(l = locals[ix].next; l; l = l->next) {			if(dtype == l->dtype)				return;		}		l = Malloc(sizeof(Local));		l->next = locals[ix].next;		locals[ix].next = l;	}	l->dtype = dtype;	frameoff = align(frameoff, cellsize[dtype]);	l->offset = frameoff;	frameoff += cellsize[dtype];} /* * Map the signature parameter types into 'locals' array. */ static voidmapmethodsig(char *sig, int isstatic){	int index; 	index = 0;	if(isstatic == 0) {		reservelocal(DIS_P, index);	/* this pointer */		index += 1;	}	sig++;	/* skip '(' */	while(sig[0] != ')') {		switch(sig[0]) {		case 'Z':		case 'B':		case 'C':		case 'S':		case 'I':			reservelocal(DIS_W, index);			index += 1;			break;		case 'F':			reservelocal(DIS_L, index);			index += 1;			break;		case 'J':		case 'D':			reservelocal(DIS_L, index);			index += 2;			break;		case 'L':		case '[':			reservelocal(DIS_P, index);			index += 1;			break;		}		sig = nextjavatype(sig);	}} /* * Map references to local variables in the Java bytecode into 'locals' array. */ static voidmaplocalrefs(void){	Jinst *j, *je; 	j = &code->j[0];	je = j + code->code_length;	while(j < je) {		switch(j->op) {		case Jiinc:			reservelocal(DIS_W, j->u.x1c.ix);			break;		case Jiload:		case Jistore:			reservelocal(DIS_W, j->u.i);			break;		case Jiload_0:		case Jistore_0:			reservelocal(DIS_W, 0);			break;		case Jiload_1:		case Jistore_1:			reservelocal(DIS_W, 1);			break;		case Jiload_2:		case Jistore_2:			reservelocal(DIS_W, 2);			break;		case Jiload_3:		case Jistore_3:			reservelocal(DIS_W, 3);			break;		case Jlload:		case Jlstore:		case Jfload:		case Jfstore:		case Jdload:		case Jdstore:			reservelocal(DIS_L, j->u.i);			break;		case Jlload_0:		case Jlstore_0:		case Jfload_0:		case Jfstore_0:		case Jdload_0:		case Jdstore_0:			reservelocal(DIS_L, 0);			break;		case Jlload_1:		case Jlstore_1:		case Jfload_1:		case Jfstore_1:		case Jdload_1:		case Jdstore_1:			reservelocal(DIS_L, 1);			break;		case Jlload_2:		case Jlstore_2:		case Jfload_2:		case Jfstore_2:		case Jdload_2:		case Jdstore_2:			reservelocal(DIS_L, 2);			break;		case Jlload_3:		case Jlstore_3:		case Jfload_3:		case Jfstore_3:		case Jdload_3:		case Jdstore_3:			reservelocal(DIS_L, 3);			break;		case Jret:		case Jaload:		case Jastore:			reservelocal(DIS_P, j->u.i);			break;		case Jaload_0:		case Jastore_0:			reservelocal(DIS_P, 0);			break;		case Jaload_1:		case Jastore_1:			reservelocal(DIS_P, 1);			break;		case Jaload_2:		case Jastore_2:			reservelocal(DIS_P, 2);			break;		case Jaload_3:		case Jastore_3:			reservelocal(DIS_P, 3);			break;		case Jwide:	/* repeat from above */			switch(j->u.w.op) {			case Jiinc:			case Jiload:			case Jistore:				reservelocal(DIS_W, j->u.w.ix);				break;			case Jlload:			case Jlstore:			case Jfload:			case Jfstore:			case Jdload:			case Jdstore:				reservelocal(DIS_L, j->u.w.ix);				break;			case Jaload:			case Jastore:			case Jret:				reservelocal(DIS_P, j->u.w.ix);				break;			}			break;		}		j += j->size;	}} /* * Prepare a method's frame prior to translating its code. */ voidopenframe(char *sig, int isstatic){	frameoff = REGSIZE;	/* 'code' can == nil; e.g, when generating <clinit> for an interface */	if(code)		nlocals = code->max_locals;	else		nlocals = 2;	locals = Mallocz(nlocals*sizeof(Local));	mapmethodsig(sig, isstatic);	if(code)		maplocalrefs();	frameoff = align(frameoff, IBY2WD);	tmpslwm = frameoff;	tmpssz = frameoff;	tmps = Mallocz(tmpssz*sizeof(Fp));} /* * Return fp index of a local variable. */ intlocalix(uchar dtype, int ix){	Local *l; 	if(dtype == locals[ix].dtype)		return locals[ix].offset;	for(l = locals[ix].next; l; l = l->next) {		if(dtype == l->dtype)			return l->offset;	}	fatal("localix: %d, %d\n", dtype, ix);	return -1;	/* for the compiler */} /* fp temporary management starts here */ static voidincref(int off){	if(off >= tmpslwm)		/* if <, then local variable */		tmps[off-tmpslwm].refcnt++;} voidacqreg(Addr *a){	switch(a->mode) {	case Anone:	case Aimm:	case Amp:	case Ampind:		break;	case Afp:		incref(a->u.offset);		break;	case Afpind:		incref(a->u.b.fi);		break;	}} /* * Reserve the fp temporaries referenced by a StkSnap of some basic block. */ voidreservereg(StkSnap *s, int sz){	int i; 	for(i = 0; i < sz; i++)		acqreg(&code->j[s[i].pc[0]].dst);} /* * Get fp offset of the next available register of the given type. */ static intgetoff(uchar dtype){	int off;	int stride; 	if(dtype == DIS_L) {		stride = IBY2LG;		off = tmpslwm % IBY2LG;	} else {		stride = IBY2WD;		off = 0;	}	while(off < tmpssz) {		if(tmps[off].refcnt == 0		&& (tmps[off].dtype == dtype || tmps[off].dtype == DIS_X)) {			return off;		}		off += stride;	}	return off;} /* * Get a register (fp offset thereof) of the appropriate type. */ intgetreg(uchar dtype){	int off;	int oldsz; 	off = getoff(dtype);	if(off >= tmpssz) {	/* increase size of temporary arena */		oldsz = tmpssz;		tmpssz += ALLOCINCR*IBY2LG;		tmps = Realloc(tmps, tmpssz*sizeof(Fp));		memset(&tmps[oldsz], 0, (ALLOCINCR*IBY2LG)*sizeof(Fp));	}	tmps[off].dtype = dtype;	if(dtype == DIS_L)	/* also reserve next word */		tmps[off+IBY2WD].dtype = dtype;	tmps[off].refcnt = 1;	if(tmpslwm+off+cellsize[dtype] > frameoff)		frameoff = tmpslwm+off+cellsize[dtype];	return tmpslwm+off;} static voiddecref(int off){	if(off >= tmpslwm) {		/* if <, then local variable */		if(--tmps[off-tmpslwm].refcnt < 0)			fatal("decref: refcnt < 0\n");	}} /* * "Free" register used by a. */ voidrelreg(Addr *a){	/* don't mess with exception object */	if(code != nil && a == &code->j[code->code_length].dst)		return;	switch(a->mode) {	case Anone:	case Aimm:	case Amp:	case Ampind:		break;	case Afp:		decref(a->u.offset);		break;	case Afpind:		decref(a->u.b.fi);		break;	}} /* * Mark all temporary fp registers as available.  Leave typing as is. */ voidclearreg(void){	int i; 	i = 0;	while(i < frameoff-tmpslwm) {		tmps[i].refcnt = 0;		i += IBY2WD;	}} /* * Calculate the type descriptor for a frame. */ static intframedesc(void){	int ln, id, i;	uchar *map;	Local *l; 	ln = frameoff / (8*IBY2WD) + (frameoff % (8*IBY2WD) != 0);	map = Mallocz(ln);	setbit(map, REFSYSEX);	/* slot for 'ref Sys->Exception' */	setbit(map, EXOBJ);	/* slot for exception object */	for(i = 0; i < nlocals; i++) {		if(locals[i].dtype == DIS_P)			setbit(map, locals[i].offset);		for(l = locals[i].next; l; l = l->next) {			if(l->dtype == DIS_P)				setbit(map, l->offset);		}	}	i = 0;	while(i < frameoff-tmpslwm) {		if(tmps[i].dtype == DIS_P)			setbit(map, tmpslwm+i);		i += IBY2WD;	}	id = descid(frameoff, ln, map);	return id;} /* * Dispense with a frame. */ intcloseframe(void){	int tid, i;	Local *l, *l2; 	/* frame size is always a multiple of 8 */	frameoff = align(frameoff, IBY2LG);	if(frameoff > maxframe)		maxframe = frameoff;	tid = framedesc();	for(i = 0; i < nlocals; i++) {		for(l = locals[i].next; l; l = l2) {			l2 = l->next;			free(l);		}	}	free(locals);	frameoff = 0;	tmpslwm = 0;

Lines 1–500 of 514.