1329 lines · 21.4 KB · Brainfuck
RawDownload
## "Simulate" the Java VM on a method.# Result: adt {	jtype:	byte;	pc:	int;}; jvmstack:	array of ref Result;	# simulated JVM stackjvmtos:		int;			# number of items in jvmstackjvmwords:	int;			# number of words that would be on JVM stackrettype:	int;			# return type of simulated method jvmpop(): ref Result{	r: ref Result; 	if(jvmtos == 0)		verifyerrormess("stack underflow");	r = jvmstack[--jvmtos];	if(r.jtype == byte 'J' || r.jtype == byte 'D')		jvmwords -= 2;	else		jvmwords -= 1;	if(jvmwords < 0)		verifyerrormess("stack underflow");	return r;} jvmpush(r: ref Result){	if(r.jtype == byte 'J' || r.jtype == byte 'D')		jvmwords += 2;	else		jvmwords += 1;	if(jvmwords > code.max_stack)		verifyerrormess("stack overflow");	jvmstack[jvmtos++] = r;} ## Initialize jvmstack to process basic block bb.# jvminit(bb: ref BB){	i: int;	r: ref Result;	s: array of ref StkSnap; 	jvmtos = 0;	jvmwords = 0;	if(int (bb.flags & (BB_FINALLY | BB_HANDLER))) {		r = ref Result(byte 'L', code.code_length);		jvmpush(r);	# push a dummy		return;	} 	# set jvmstack to bb.entrystk	s = bb.entrystk;	for(i = 0; i < bb.entrysz; i++) {		r = ref Result(s[i].jtype, s[i].pc[0]);		jvmpush(r);	}} typecheck(r: ref Result, jtype: byte){	# assumes 'L' and '[' are interchangeable	if(r.jtype != jtype && (int r.jtype + int jtype) != 'L' + '[')		verifyerror(code.j[r.pc]);} jvmtype(jtype: int): byte{	case jtype {	'Z' or	'B' or	'C' or	'S' =>		jtype = 'I';	}	return byte jtype;} srcalloc(j: ref Jinst, n: int){	j.nsrc = n;	j.src = array [n] of int;} iconst(j: ref Jinst, ival: int){	r: ref Result; 	addrimm(j.dst, ival);	r = ref Result(byte 'I', j.pc);	j.jtype = byte 'I';	jvmpush(r);} mpconst(j: ref Jinst, jtype: int, off: int){	r: ref Result; 	addrsind(j.dst, Amp, off);	r = ref Result(byte jtype, j.pc);	j.jtype = byte jtype;	jvmpush(r);} verifyindex(j: ref Jinst, jtype: int, ix: int){	n: int; 	case jtype {	'I' or	'F' or	'L' =>		n = code.max_locals-1;	'J' or	'D' =>		n = code.max_locals-2;	}	if(ix > n)		verifyerror(j);} getfpoff(jtype: int, ix: int): int{	off: int; 	case jtype {	'I' =>		off = localix(DIS_W, ix);	'J' or	'F' or	'D' =>		off = localix(DIS_L, ix);	'L' =>		off = localix(DIS_P, ix);	}	return off;} javaload(j: ref Jinst, jtype: int, ix: int){	r: ref Result; 	verifyindex(j, jtype, ix);	addrsind(j.dst, Afp, getfpoff(jtype, ix));	r = ref Result(byte jtype, j.pc);	j.jtype = byte jtype;	jvmpush(r);} javastore(j: ref Jinst, jtype: int, ix: int){	r: ref Result; 	verifyindex(j, jtype, ix); 	srcalloc(j, 1); 	r = jvmpop();	typecheck(r, byte jtype);	j.src[0] = r.pc; 	addrsind(j.dst, Afp, getfpoff(jtype, ix));} arrayload(j: ref Jinst, jtype: int){	r: ref Result; 	srcalloc(j, 2); 	r = jvmpop();	typecheck(r, byte 'I');	j.src[1] = r.pc; 	r = jvmpop();	typecheck(r, byte '[');	j.src[0] = r.pc; 	addrsind(j.dst, Afp, -1);	r = ref Result(byte jtype, j.pc);	j.jtype = byte jtype;	jvmpush(r);} arraystore(j: ref Jinst, jtype: int){	r: ref Result; 	srcalloc(j, 3); 	r = jvmpop();	typecheck(r, byte jtype);	j.src[2] = r.pc; 	r = jvmpop();	typecheck(r, byte 'I');	j.src[1] = r.pc; 	r = jvmpop();	typecheck(r, byte '[');	j.src[0] = r.pc; } binop(j: ref Jinst, loptype: int, roptype: int, dsttype: int){	r: ref Result; 	srcalloc(j, 2); 	r = jvmpop();	typecheck(r, byte roptype);	j.src[1] = r.pc; 	r = jvmpop();	typecheck(r, byte loptype);	j.src[0] = r.pc; 	addrsind(j.dst, Afp, -1);	r = ref Result(byte dsttype, j.pc);	j.jtype = byte dsttype;	jvmpush(r);} unop(j: ref Jinst, srctype: int, dsttype: int){	r: ref Result; 	srcalloc(j, 1); 	r = jvmpop();	typecheck(r, byte srctype);	j.src[0] = r.pc; 	addrsind(j.dst, Afp, -1);	r = ref Result(byte dsttype, j.pc);	j.jtype = byte dsttype;	jvmpush(r);} ## If the local variable being stored into corresponds to a local# that is on the stack, then an explicit mov_ MUST be generated# for the load instruction that put it on the stack.# storechk(six: int, stype: int){	i, lix: int;	ltype: byte;	j: ref Jinst;	jpi: ref Jinst.Pi;	jpw: ref Jinst.Pw; 	for(i = 0; i < jvmtos; i++) {		j = code.j[jvmstack[i].pc];		lix = -1;		pick jp := j {		Pi =>			jpi = jp;		Pw =>			jpw = jp;		}		case int j.op {		Jiload or		Jlload or		Jfload or		Jdload or		Jaload =>			lix = jpi.i;		Jiload_0 or		Jlload_0 or		Jfload_0 or		Jdload_0 or		Jaload_0 =>			lix = 0;		Jiload_1 or		Jlload_1 or		Jfload_1 or		Jdload_1 or		Jaload_1 =>			lix = 1;		Jiload_2 or		Jlload_2 or		Jfload_2 or		Jdload_2 or		Jaload_2 =>			lix = 2;		Jiload_3 or		Jlload_3 or		Jfload_3 or		Jdload_3 or		Jaload_3 =>			lix = 3;		Jwide =>			case int jpw.w.op {			Jiload or			Jlload or			Jfload or			Jdload or			Jaload =>				lix = jpw.w.ix;			}		}		ltype = byte '-';		case int j.op {		Jiload or		Jiload_0 or		Jiload_1 or		Jiload_2 or		Jiload_3 =>			ltype = byte 'I';		Jlload or		Jlload_0 or		Jlload_1 or		Jlload_2 or		Jlload_3 =>			ltype = byte 'J';		Jfload or		Jfload_0 or		Jfload_1 or		Jfload_2 or		Jfload_3 =>			ltype = byte 'F';		Jdload or		Jdload_0 or		Jdload_1 or		Jdload_2 or		Jdload_3 =>			ltype = byte 'D';		Jaload or		Jaload_0 or		Jaload_1 or		Jaload_2 or		Jaload_3 =>			ltype = byte 'L';		Jwide =>			case int jpw.w.op {			Jiload =>				ltype = byte 'I';			Jlload =>				ltype = byte 'J';			Jfload =>				ltype = byte 'F';			Jdload =>				ltype = byte 'D';			Jaload =>				ltype = byte 'L';			}		}		if(lix == six && ltype == byte stype && j.movsrc != nil && j.movsrc.mode == byte Anone) {			*j.movsrc = *j.dst;			addrsind(j.dst, Afp, -1);		}	}} useone(j: ref Jinst, jtype: int){	r: ref Result; 	srcalloc(j, 1); 	r = jvmpop();	typecheck(r, byte jtype);	j.src[0] = r.pc;} usetwo(j: ref Jinst, loptype: byte, roptype: byte){	r: ref Result; 	srcalloc(j, 2); 	r = jvmpop();	typecheck(r, roptype);	j.src[1] = r.pc; 	r = jvmpop();	typecheck(r, loptype);	j.src[0] = r.pc;} javanew(j: ref Jinst.Pi){	r: ref Result;	name: string; 	name = CLASSNAME(j.i);	if(name[0] == '[')		verifyerror(j); 	addrsind(j.dst, Afp, -1);	r = ref Result(byte 'L', j.pc);	j.jtype = byte 'L';	jvmpush(r);} checkdim(j: ref Jinst, ix: int): int{	ndim: int;	name: string; 	ndim = 0;	name = CLASSNAME(ix);	while(name[ndim] == '[')		ndim++;	if(ndim > 255)		verifyerror(j);	return ndim;} anewarray(j: ref Jinst.Pi){	checkdim(j, j.i);	unop(j, 'I', '[');} multianewarray(j: ref Jinst.Px2d){	r: ref Result;	i, ndim: int; 	ndim = checkdim(j, j.x2d.ix);	if(ndim == 0 || j.x2d.dim > ndim)		verifyerror(j); 	srcalloc(j, j.x2d.dim);	for(i = j.x2d.dim-1; i >= 0; i--) {		r = jvmpop();		typecheck(r, byte 'I');		j.src[i] = r.pc;	} 	addrsind(j.dst, Afp, -1);	r = ref Result(byte '[', j.pc);	j.jtype = byte '[';	jvmpush(r);} getname(j: ref Jinst): string{	ix: int; 	pick jp := j {	Pi =>		ix = jp.i;	Px2c0 =>		ix = jp.x2c0.ix;	* =>		badpick("getname[Pi|Px2c0]");	}	pick c := class.cps[ix] {	Pfmiref =>		pick n := class.cps[c.fmiref.name_type_index] {		Pnat =>			return STRING(n.nat.name_index);		* =>			badpick("getname[Pnat]");		}	* =>		badpick("getname[Pfmiref]");	}	return nil;} getsig(j: ref Jinst): string{	ix: int; 	pick jp := j {	Pi =>		ix = jp.i;	Px2c0 =>		ix = jp.x2c0.ix;	* =>		badpick("getsig[Pi|Px2c0]");	}	pick c := class.cps[ix] {	Pfmiref =>		pick n := class.cps[c.fmiref.name_type_index] {		Pnat =>			return STRING(n.nat.sig_index);		* =>			badpick("getsig[Pnat]");		}	* =>		badpick("getsig[Pfmiref]");	}	return nil;} 

Lines 1–500 of 1329.