📄 insgen.java
字号:
gengoto(d, m, ins, ins.more[0]); d.println("\t}"); break; case LKPSW: // lookupswitch d.println("\tswitch (" + stacktop(ins) + ") {"); for (int i = 2; i < ins.more.length; i += 2) { d.print("\t\tcase " + ins.more[i] + ": \t"); gengoto(d, m, ins, ins.more[i + 1]); } d.print("\t\tdefault:\t"); gengoto(d, m, ins, ins.more[0]); d.println("\t}"); break; case GOTO: // goto d.print("\t"); gengoto(d, m, ins, ins.val); break; case JSR: // jsr d.println("\ta" + (ins.before.length() + 1) + " = (Object)(long)" + target(m, ins.pc + ins.length) + ";"); d.println("\tgoto L" + target(m, ins.val) + ";"); break; case RET: // ret [to pc set by jsr] // to do without macro call: // d.println("\ttgt = iv" + ins.val + ";"); // d.println("\tgoto TOP;"); d.println("\tRETTO(" + ins.pc + ",(int)(long)av" + ins.val + ");"); break; case IVIRT: // invokevirtual r = (FieldRef)ins.con.value; n = argindex(ins, r.signature); checkref(d, ins, n + 1); s = "((struct in_" + Names.hashclass(r.cl.name) + "*)" + ins.before.charAt(n) + (n + 1) + ")->class->M.\n\t\t" + Names.hashmethod(r.name, r.cl.name, r.signature) + ".f"; invoke(d, ins, (MethodRef)r, s); break; case INONV: // invokenonvirtual r = (FieldRef)ins.con.value; checkref(d, ins, argindex(ins, r.signature) + 1); invoke(d, ins, (MethodRef)r, Names.hashmethod(r.name,r.cl.name,r.signature)); break; case ISTAT: // invokestatic r = (FieldRef)ins.con.value; invoke(d, ins, (MethodRef)r, Names.hashmethod(r.name,r.cl.name,r.signature)); break; case IINTR: // invokeinterface r = (FieldRef)ins.con.value; n = argindex(ins, r.signature); checkref(d, ins, n + 1); t1 = Repr.ctype(r.signature.charAt(r.signature.indexOf(')') + 1)); s = "(*(" + t1 + "(*)())findinterface(a" + (n + 1) + "," + Names.hashinterface(r.name, r.signature) + ")->f)"; invoke(d, ins, (MethodRef)r, s); break; case RETV: // ireturn, areturn, ... if (MethGen.needSwitch(m)) { d.println("\trv = " + stacktop(ins) + ";"); d.println("\tgoto RETURN;"); } else d.println("\treturn " + stacktop(ins) + ";"); break; case RETRN: // return if (MethGen.needSwitch(m)) d.println("\tgoto RETURN;"); else d.println("\treturn;"); break; case THROW: // athrow d.println("\tathrow(" + stacktop(ins) + ");"); break; case MENTR: // monitorenter // monitorenter(tos, thread, curpc + 1, &pc) d.println("\tmonitorenter(" + stacktop(ins) + ", tdata, " + (ins.pc + 1) + ", &pc);"); break; case MEXIT: // monitorexit // monitorexit(tos, thread, curpc, &pc) d.println("\tmonitorexit(" + stacktop(ins) + ", tdata, " + (ins.pc + 1) + ", &pc);"); break; default: throw new VerifyError ("unimplemented opcode " + o.name + " at pc=" + ins.pc); }}// ancestor(cl, h) -- is the hashed classname h our class or a superclass? static private boolean ancestor(ClassData cl, String s){ for (; cl != null; cl = cl.superclass) if (s.equals(cl.cname)) return true; return false;}// gengoto(d, m, ins, pc) -- generate goto from ins to pcstatic private void gengoto(PrintWriter d, Method m, Instr ins, int pc){ int lbl = target(m, pc);// to do without macro calls:// d.println("goto L" + lbl + ";"); if (ins.pc > pc) d.println("GOBACK(" + ins.pc + ",L" + lbl + ");"); else d.println("GOTO(" + ins.pc + ",L" + lbl + ");");}// target(m, pc) -- return label corresponding to jump target given in pc termsstatic private int target(Method m, int pc){ return m.instrs[m.pcmap[pc]].label;}// checkref(d, ins, n) -- gen code to check that stack variable n is non-null//// If n >= 0, the variable name is "a" + n;// If n < 0, the variable name is stackvar(ins,n);static private void checkref(PrintWriter d, Instr ins, int n){ String s; if (n >= 0) s = "a" + n; else s = stackvar(ins, n); // Make this multi-line, so we can set a breakpoint on the body d.println("\tif (!" + s + ") { "); d.println("\t\tSetNPESource(); goto NULLX;"); d.println("\t}"); MethGen.nullJump = true; // set flag in method generator}// ckinstance(ins, classname) -- return code that checks "instance of" relation//// Let S be the type of the (non-null) object on top of the stack.// Let T be the target type indicated in the instruction.//// The conditions under which S is an instance of T, or S is castable to T,// depend on type T.//// If T is java.lang.Object: always true, even if S is an array// If T is a class: true if S is T or a subclass of T// (always true of T is java.lang.Object)// or if S implements T// If T is array of primitive: true if S is same class as T// (array of same primitive type)// If T is array of object TC: true if S is array of object SC and// SC is instance of TCstatic private String ckinstance(Instr ins, String classname){ // handle special case of java.lang.Object if (classname.equals("java.lang.Object")) return "1"; // handle cast to other non-array object if (classname.charAt(0) != '[') return "(c0 = *(Class*)" + stacktop(ins) + ", c1 = &cl_" + Names.hashclass(classname) + ".C,\n\t\t\t(c1->flags & 1) ? " + // IS_INTERFACE "instanceof(" + stacktop(ins) + ",c1,0) :" + "\n\t\t\t\t(c0->nsupers >= c1->nsupers &&" + "\n\t\t\t\tc0->supers[c0->nsupers - c1->nsupers] == c1))"; // handle "array of primitive" case char c = classname.charAt(1); if (c != '[' && c != 'L') return "(*(struct class **)" + stacktop(ins) + " == &a" + Names.classref(classname.substring(1)) + ".C)"; // handle "array of object" case int n; for (n = 0; classname.charAt(n) == '['; n++) ; // n = class dimensions return "instanceof(" + stacktop(ins) + ",&" + Names.classref(classname.substring(n)) + "," + n + ")";}// invoke(d, ins, r, cname) -- generate code to invoke cnamestatic private void invoke(PrintWriter d, Instr ins, MethodRef r, String cname){ int i = argindex(ins, r.signature); // start with result assignment, if any, and function name if (i == ins.after.length()) // if no result pushed d.print("\t"); else d.print(assign(ins)); // add name or expression that identifies the function d.print(cname + "("); // generate argument list int nargs = 0; for (; i < ins.before.length(); i++) { if (ins.before.charAt(i) != 'x') { if (nargs++ != 0) d.print(","); d.print(ins.before.substring(i, i+1) + (i + 1)); } } d.println(");");}// argindex(ins, signature) -- return index of first arg of method callstatic private int argindex(Instr ins, String signature){ char c = signature.charAt(signature.indexOf(')') + 1); // return type int n = ins.after.length(); // stack size after call if (c == 'J' || c == 'D') return n - 2; // long or double returns add two words else if (c == 'V') return n; // no compensation for void return else return n - 1; // other return types add one word}// assign(ins) -- return beginning of assignment stmt ("\tvarname = ").static final String assign(Instr ins){ return "\t" + ins.after.substring(ins.after.length() - 1) + ins.after.length() + " = ";}// stacktop(ins) -- return name of top-of-stack variable.static final String stacktop(Instr ins){ return ins.before.substring(ins.before.length() - 1) + ins.before.length();}// stack2nd(ins) -- return name of second-from-top stack variable.static final String stack2nd(Instr ins){ int len = ins.before.length(); if (ins.before.charAt(len - 2) == 'x') // if double-sized item on top return ins.before.substring(len - 3, len - 2) + (len - 2); else return ins.before.substring(len - 2, len - 1) + (len - 1);}// stackvar(ins, n) -- return name of stack var at n (-1 = top, -2 = 2nd, etc.)//// n counts actual stack variables, not stack positions static final String stackvar(Instr ins, int n){ int i = ins.before.length(); while (n < 0) if (ins.before.charAt(--i) != 'x') n++; return ins.before.substring(i, i + 1) + (i + 1);}// stackAt(ins, n) -- return name of stack var at position n (-1, -2, -3)//// n reflects position on stack without regard to double-wide variablesstatic final String stackAt(Instr ins, int n){ int i = ins.before.length() + n; return ins.before.substring(i, i + 1) + (i + 1);}} // class InsGen
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -