#include "java.h"#include "javaisa.h" /* * "Simulate" the Java VM on a method. */ typedef struct Result Result; struct Result { uchar jtype; int pc;}; static Result *jvmstack; /* simulated JVM stack */static int jvmtos; /* number of items in jvmstack */static int jvmwords; /* number of words that would be on JVM stack */static uchar rettype; /* return type of simulated method */ static Resultjvmpop(void){ Result r; if(jvmtos == 0) goto bad; r = jvmstack[--jvmtos]; if(r.jtype == 'J' || r.jtype == 'D') jvmwords -= 2; else jvmwords -= 1; if(jvmwords < 0)bad: verifyerrormess("stack underflow"); return r;} static voidjvmpush(Result r){ if(r.jtype == 'J' || r.jtype == 'D') jvmwords += 2; else jvmwords += 1; if(jvmwords > code->max_stack) verifyerrormess("stack overflow"); jvmstack[jvmtos++] = r;} /* * Initialize jvmstack to process basic block bb. */ static voidjvminit(BB *bb){ int i; Result r; StkSnap *s; jvmtos = 0; jvmwords = 0; if(bb->flags & (BB_FINALLY | BB_HANDLER)) { r.jtype = 'L'; r.pc = 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.jtype = s[i].jtype; r.pc = s[i].pc[0]; jvmpush(r); }} static voidtypecheck(Result *r, uchar jtype){ /* assumes 'L' and '[' are interchangeable */ if(r->jtype != jtype && r->jtype + jtype != 'L' + '[') verifyerror(&code->j[r->pc]);} static ucharjvmtype(uchar jtype){ switch(jtype) { case 'Z': case 'B': case 'C': case 'S': jtype = 'I'; break; } return jtype;} static voidsetresult(Result *r, uchar jtype, Jinst *j){ r->jtype = jtype; r->pc = j->pc; j->jtype = jtype;} static voidsrcalloc(Jinst *j, int n){ j->nsrc = n; j->src = Malloc(n*sizeof(int));} static voidiconst(Jinst *j, int ival){ Result r; addrimm(&j->dst, ival); setresult(&r, 'I', j); jvmpush(r);} static voidmpconst(Jinst *j, uchar jtype, int off){ Result r; addrsind(&j->dst, Amp, off); setresult(&r, jtype, j); jvmpush(r);} static voidverifyindex(Jinst *j, uchar jtype, int ix){ int n; switch(jtype) { case 'I': case 'F': case 'L': n = code->max_locals-1; break; case 'J': case 'D': n = code->max_locals-2; break; default: fatal("verifyindex: invalid jtype"); return; } if(ix > n) verifyerror(j);} static intgetfpoff(uchar jtype, int ix){ int off; switch(jtype) { case 'I': off = localix(DIS_W, ix); break; case 'J': case 'F': case 'D': off = localix(DIS_L, ix); break; case 'L': off = localix(DIS_P, ix); break; default: fatal("getfpoff: invalid jtype"); return -1; } return off;} static voidjavaload(Jinst *j, uchar jtype, int ix){ Result r; verifyindex(j, jtype, ix); addrsind(&j->dst, Afp, getfpoff(jtype, ix)); setresult(&r, jtype, j); jvmpush(r);} static voidjavastore(Jinst *j, uchar jtype, int ix){ Result r; verifyindex(j, jtype, ix); srcalloc(j, 1); r = jvmpop(); typecheck(&r, jtype); j->src[0] = r.pc; addrsind(&j->dst, Afp, getfpoff(jtype, ix));} static voidarrayload(Jinst *j, uchar jtype){ Result r; srcalloc(j, 2); r = jvmpop(); typecheck(&r, 'I'); j->src[1] = r.pc; r = jvmpop(); typecheck(&r, '['); j->src[0] = r.pc; addrsind(&j->dst, Afp, -1); setresult(&r, jtype, j); jvmpush(r);} static voidarraystore(Jinst *j, uchar jtype){ Result r; srcalloc(j, 3); r = jvmpop(); typecheck(&r, jtype); j->src[2] = r.pc; r = jvmpop(); typecheck(&r, 'I'); j->src[1] = r.pc; r = jvmpop(); typecheck(&r, '['); j->src[0] = r.pc; } static voidbinop(Jinst *j, uchar loptype, uchar roptype, uchar dsttype){ Result r; srcalloc(j, 2); r = jvmpop(); typecheck(&r, roptype); j->src[1] = r.pc; r = jvmpop(); typecheck(&r, loptype); j->src[0] = r.pc; addrsind(&j->dst, Afp, -1); setresult(&r, dsttype, j); jvmpush(r);} static voidunop(Jinst *j, uchar srctype, uchar dsttype){ Result r; srcalloc(j, 1); r = jvmpop(); typecheck(&r, srctype); j->src[0] = r.pc; addrsind(&j->dst, Afp, -1); setresult(&r, dsttype, j); 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. */ static voidstorechk(int six, uchar stype){ int i, lix; uchar ltype; Jinst *j; for(i = 0; i < jvmtos; i++) { j = &code->j[jvmstack[i].pc]; lix = -1; switch(j->op) { case Jiload: case Jlload: case Jfload: case Jdload: case Jaload: lix = j->u.i; break; case Jiload_0: case Jlload_0: case Jfload_0: case Jdload_0: case Jaload_0: lix = 0; break; case Jiload_1: case Jlload_1: case Jfload_1: case Jdload_1: case Jaload_1: lix = 1; break; case Jiload_2: case Jlload_2: case Jfload_2: case Jdload_2: case Jaload_2: lix = 2; break; case Jiload_3: case Jlload_3: case Jfload_3: case Jdload_3: case Jaload_3: lix = 3; break; case Jwide: switch(j->u.w.op) { case Jiload: case Jlload: case Jfload: case Jdload: case Jaload: lix = j->u.w.ix; } break; } ltype = '-'; switch(j->op) { case Jiload: case Jiload_0: case Jiload_1: case Jiload_2: case Jiload_3: ltype = 'I'; break; case Jlload: case Jlload_0: case Jlload_1: case Jlload_2: case Jlload_3: ltype = 'J'; break; case Jfload: case Jfload_0: case Jfload_1: case Jfload_2: case Jfload_3: ltype = 'F'; break; case Jdload: case Jdload_0: case Jdload_1: case Jdload_2: case Jdload_3: ltype = 'D'; break; case Jaload: case Jaload_0: case Jaload_1: case Jaload_2: case Jaload_3: ltype = 'L'; break; case Jwide: switch(j->u.w.op) { case Jiload: ltype = 'I'; break; case Jlload: ltype = 'J'; break; case Jfload: ltype = 'F'; break; case Jdload: ltype = 'D'; break; case Jaload: ltype = 'L'; break; } break; } if(lix == six && ltype == stype && j->movsrc.mode == Anone) { j->movsrc = j->dst; addrsind(&j->dst, Afp, -1); } }} static voiduseone(Jinst *j, uchar jtype){ Result r; srcalloc(j, 1); r = jvmpop(); typecheck(&r, jtype); j->src[0] = r.pc;} static voidusetwo(Jinst *j, uchar loptype, uchar roptype){ Result r; srcalloc(j, 2); r = jvmpop(); typecheck(&r, roptype); j->src[1] = r.pc; r = jvmpop(); typecheck(&r, loptype); j->src[0] = r.pc;} static voidjavanew(Jinst *j){ Result r; char *name; name = CLASSNAME(j->u.i); if(name[0] == '[') verifyerror(j); addrsind(&j->dst, Afp, -1); setresult(&r, 'L', j); jvmpush(r); crefenter(name, j->bb);} static intcheckdim(Jinst *j, int ix){ int ndim; char *name; ndim = 0; name = CLASSNAME(ix); while(name[0] == '[') { ndim++; name++; } if(ndim > 255) verifyerror(j); crefenter(name, j->bb); return ndim;} static voidanewarray(Jinst *j){ checkdim(j, j->u.i); unop(j, 'I', '[');} static voidmultianewarray(Jinst *j){ Result r; int i, ndim; ndim = checkdim(j, j->u.x2d.ix); if(ndim == 0 || j->u.x2d.dim > ndim) verifyerror(j); srcalloc(j, j->u.x2d.dim); for(i = j->u.x2d.dim-1; i >= 0; i--) { r = jvmpop(); typecheck(&r, 'I'); j->src[i] = r.pc; } addrsind(&j->dst, Afp, -1);Lines 1–500 of 1509. Load more
#include "java.h" #include "javaisa.h" /* * "Simulate" the Java VM on a method. */ typedef struct Result Result; struct Result { uchar jtype; int pc; }; static Result *jvmstack; /* simulated JVM stack */ static int jvmtos; /* number of items in jvmstack */ static int jvmwords; /* number of words that would be on JVM stack */ static uchar rettype; /* return type of simulated method */ static Result jvmpop(void) { Result r; if(jvmtos == 0) goto bad; r = jvmstack[--jvmtos]; if(r.jtype == 'J' || r.jtype == 'D') jvmwords -= 2; else jvmwords -= 1; if(jvmwords < 0) bad: verifyerrormess("stack underflow"); return r; } static void jvmpush(Result r) { if(r.jtype == 'J' || r.jtype == 'D') jvmwords += 2; else jvmwords += 1; if(jvmwords > code->max_stack) verifyerrormess("stack overflow"); jvmstack[jvmtos++] = r; } /* * Initialize jvmstack to process basic block bb. */ static void jvminit(BB *bb) { int i; Result r; StkSnap *s; jvmtos = 0; jvmwords = 0; if(bb->flags & (BB_FINALLY | BB_HANDLER)) { r.jtype = 'L'; r.pc = 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.jtype = s[i].jtype; r.pc = s[i].pc[0]; jvmpush(r); } } static void typecheck(Result *r, uchar jtype) { /* assumes 'L' and '[' are interchangeable */ if(r->jtype != jtype && r->jtype + jtype != 'L' + '[') verifyerror(&code->j[r->pc]); } static uchar jvmtype(uchar jtype) { switch(jtype) { case 'Z': case 'B': case 'C': case 'S': jtype = 'I'; break; } return jtype; } static void setresult(Result *r, uchar jtype, Jinst *j) { r->jtype = jtype; r->pc = j->pc; j->jtype = jtype; } static void srcalloc(Jinst *j, int n) { j->nsrc = n; j->src = Malloc(n*sizeof(int)); } static void iconst(Jinst *j, int ival) { Result r; addrimm(&j->dst, ival); setresult(&r, 'I', j); jvmpush(r); } static void mpconst(Jinst *j, uchar jtype, int off) { Result r; addrsind(&j->dst, Amp, off); setresult(&r, jtype, j); jvmpush(r); } static void verifyindex(Jinst *j, uchar jtype, int ix) { int n; switch(jtype) { case 'I': case 'F': case 'L': n = code->max_locals-1; break; case 'J': case 'D': n = code->max_locals-2; break; default: fatal("verifyindex: invalid jtype"); return; } if(ix > n) verifyerror(j); } static int getfpoff(uchar jtype, int ix) { int off; switch(jtype) { case 'I': off = localix(DIS_W, ix); break; case 'J': case 'F': case 'D': off = localix(DIS_L, ix); break; case 'L': off = localix(DIS_P, ix); break; default: fatal("getfpoff: invalid jtype"); return -1; } return off; } static void javaload(Jinst *j, uchar jtype, int ix) { Result r; verifyindex(j, jtype, ix); addrsind(&j->dst, Afp, getfpoff(jtype, ix)); setresult(&r, jtype, j); jvmpush(r); } static void javastore(Jinst *j, uchar jtype, int ix) { Result r; verifyindex(j, jtype, ix); srcalloc(j, 1); r = jvmpop(); typecheck(&r, jtype); j->src[0] = r.pc; addrsind(&j->dst, Afp, getfpoff(jtype, ix)); } static void arrayload(Jinst *j, uchar jtype) { Result r; srcalloc(j, 2); r = jvmpop(); typecheck(&r, 'I'); j->src[1] = r.pc; r = jvmpop(); typecheck(&r, '['); j->src[0] = r.pc; addrsind(&j->dst, Afp, -1); setresult(&r, jtype, j); jvmpush(r); } static void arraystore(Jinst *j, uchar jtype) { Result r; srcalloc(j, 3); r = jvmpop(); typecheck(&r, jtype); j->src[2] = r.pc; r = jvmpop(); typecheck(&r, 'I'); j->src[1] = r.pc; r = jvmpop(); typecheck(&r, '['); j->src[0] = r.pc; } static void binop(Jinst *j, uchar loptype, uchar roptype, uchar dsttype) { Result r; srcalloc(j, 2); r = jvmpop(); typecheck(&r, roptype); j->src[1] = r.pc; r = jvmpop(); typecheck(&r, loptype); j->src[0] = r.pc; addrsind(&j->dst, Afp, -1); setresult(&r, dsttype, j); jvmpush(r); } static void unop(Jinst *j, uchar srctype, uchar dsttype) { Result r; srcalloc(j, 1); r = jvmpop(); typecheck(&r, srctype); j->src[0] = r.pc; addrsind(&j->dst, Afp, -1); setresult(&r, dsttype, j); 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. */ static void storechk(int six, uchar stype) { int i, lix; uchar ltype; Jinst *j; for(i = 0; i < jvmtos; i++) { j = &code->j[jvmstack[i].pc]; lix = -1; switch(j->op) { case Jiload: case Jlload: case Jfload: case Jdload: case Jaload: lix = j->u.i; break; case Jiload_0: case Jlload_0: case Jfload_0: case Jdload_0: case Jaload_0: lix = 0; break; case Jiload_1: case Jlload_1: case Jfload_1: case Jdload_1: case Jaload_1: lix = 1; break; case Jiload_2: case Jlload_2: case Jfload_2: case Jdload_2: case Jaload_2: lix = 2; break; case Jiload_3: case Jlload_3: case Jfload_3: case Jdload_3: case Jaload_3: lix = 3; break; case Jwide: switch(j->u.w.op) { case Jiload: case Jlload: case Jfload: case Jdload: case Jaload: lix = j->u.w.ix; } break; } ltype = '-'; switch(j->op) { case Jiload: case Jiload_0: case Jiload_1: case Jiload_2: case Jiload_3: ltype = 'I'; break; case Jlload: case Jlload_0: case Jlload_1: case Jlload_2: case Jlload_3: ltype = 'J'; break; case Jfload: case Jfload_0: case Jfload_1: case Jfload_2: case Jfload_3: ltype = 'F'; break; case Jdload: case Jdload_0: case Jdload_1: case Jdload_2: case Jdload_3: ltype = 'D'; break; case Jaload: case Jaload_0: case Jaload_1: case Jaload_2: case Jaload_3: ltype = 'L'; break; case Jwide: switch(j->u.w.op) { case Jiload: ltype = 'I'; break; case Jlload: ltype = 'J'; break; case Jfload: ltype = 'F'; break; case Jdload: ltype = 'D'; break; case Jaload: ltype = 'L'; break; } break; } if(lix == six && ltype == stype && j->movsrc.mode == Anone) { j->movsrc = j->dst; addrsind(&j->dst, Afp, -1); } } } static void useone(Jinst *j, uchar jtype) { Result r; srcalloc(j, 1); r = jvmpop(); typecheck(&r, jtype); j->src[0] = r.pc; } static void usetwo(Jinst *j, uchar loptype, uchar roptype) { Result r; srcalloc(j, 2); r = jvmpop(); typecheck(&r, roptype); j->src[1] = r.pc; r = jvmpop(); typecheck(&r, loptype); j->src[0] = r.pc; } static void javanew(Jinst *j) { Result r; char *name; name = CLASSNAME(j->u.i); if(name[0] == '[') verifyerror(j); addrsind(&j->dst, Afp, -1); setresult(&r, 'L', j); jvmpush(r); crefenter(name, j->bb); } static int checkdim(Jinst *j, int ix) { int ndim; char *name; ndim = 0; name = CLASSNAME(ix); while(name[0] == '[') { ndim++; name++; } if(ndim > 255) verifyerror(j); crefenter(name, j->bb); return ndim; } static void anewarray(Jinst *j) { checkdim(j, j->u.i); unop(j, 'I', '['); } static void multianewarray(Jinst *j) { Result r; int i, ndim; ndim = checkdim(j, j->u.x2d.ix); if(ndim == 0 || j->u.x2d.dim > ndim) verifyerror(j); srcalloc(j, j->u.x2d.dim); for(i = j->u.x2d.dim-1; i >= 0; i--) { r = jvmpop(); typecheck(&r, 'I'); j->src[i] = r.pc; } addrsind(&j->dst, Afp, -1);