public String _toString() { StringBuffer sb = new StringBuffer(); sb.append( method.getDeclaringClass() == JSSA.this.method.getDeclaringClass() ? method.name : (method.getDeclaringClass() + "." + method.name)); args(sb); return sb.toString(); }
private Object addOp(int op, Object arg) { int i1 = 0; int i2 = 0; if (op == WIDE) { MethodGen.Wide w = (MethodGen.Wide) arg; op = w.op; arg = null; i1 = w.varNum; i2 = w.n; } if (op == IINC) { MethodGen.Pair p = (MethodGen.Pair) arg; arg = null; i1 = p.i1; i2 = p.i2; } switch (op) { case NOP: return null; // Stack manipulations // ////////////////////////////////////////////////////////////////////////////// case ACONST_NULL: push(new Constant(null)); return null; case ICONST_M1: push(new Constant(-1)); return null; case ICONST_0: case LCONST_0: case FCONST_0: case DCONST_0: push(new Constant(0)); return null; case ICONST_1: case LCONST_1: case FCONST_1: case DCONST_1: push(new Constant(1)); return null; case ICONST_2: case FCONST_2: push(new Constant(2)); return null; case ICONST_3: push(new Constant(3)); return null; case ICONST_4: push(new Constant(4)); return null; case ICONST_5: push(new Constant(5)); return null; case ILOAD: case LLOAD: case FLOAD: case DLOAD: case ALOAD: push(local[i1]); return null; case ILOAD_0: case LLOAD_0: case FLOAD_0: case DLOAD_0: case ALOAD_0: push(local[0]); return null; case ILOAD_1: case LLOAD_1: case FLOAD_1: case DLOAD_1: case ALOAD_1: push(local[1]); return null; case ALOAD_2: case DLOAD_2: case FLOAD_2: case LLOAD_2: case ILOAD_2: push(local[2]); return null; case ILOAD_3: case LLOAD_3: case FLOAD_3: case DLOAD_3: case ALOAD_3: push(local[3]); return null; case ISTORE: case LSTORE: case FSTORE: case DSTORE: case ASTORE: local[i1] = pop(); return null; case ISTORE_0: case LSTORE_0: case FSTORE_0: case DSTORE_0: case ASTORE_0: local[0] = pop(); return null; case ISTORE_1: case LSTORE_1: case FSTORE_1: case DSTORE_1: case ASTORE_1: local[1] = pop(); return null; case ASTORE_2: case DSTORE_2: case FSTORE_2: case LSTORE_2: case ISTORE_2: local[2] = pop(); return null; case ISTORE_3: case LSTORE_3: case FSTORE_3: case DSTORE_3: case ASTORE_3: local[3] = pop(); return null; case POP: pop(); return null; case POP2: pop(); pop(); return null; case DUP: push(stack[sp - 1]); return null; case DUP2: push(stack[sp - 2]); push(stack[sp - 2]); return null; // Conversions // ////////////////////////////////////////////////////////////////////////////// // coercions are added as-needed when converting from JSSA back to bytecode, so we can // simply discard them here (assuming the bytecode we're reading in was valid in the first // place) case I2L: case F2L: case D2L: push(new Cast(pop(), Type.LONG)); return null; case I2F: case L2F: case D2F: push(new Cast(pop(), Type.FLOAT)); return null; case I2D: case L2D: case F2D: push(new Cast(pop(), Type.DOUBLE)); return null; case L2I: case F2I: case D2I: push(new Cast(pop(), Type.INT)); return null; case I2B: push(new Cast(pop(), Type.BYTE)); return null; case I2C: push(new Cast(pop(), Type.CHAR)); return null; case I2S: push(new Cast(pop(), Type.SHORT)); return null; case SWAP: { Expr e1 = pop(), e2 = pop(); push(e2); push(e1); return null; } // Math ////////////////////////////////////////////////////////////////////////////// case IADD: case LADD: case FADD: case DADD: push(new Add(pop(), pop())); return null; case ISUB: case LSUB: case FSUB: case DSUB: push(new Sub(pop(), pop())); return null; case IMUL: case LMUL: case FMUL: case DMUL: push(new Mul(pop(), pop())); return null; case IREM: case LREM: case FREM: case DREM: push(new Rem(pop(), pop())); return null; // case INEG: case LNEG: case FNEG: case DNEG: push(new Neg(pop())); return null; case IDIV: case LDIV: case FDIV: case DDIV: push(new Div(pop(), pop())); return null; case ISHL: case LSHL: push(new Shl(pop(), pop())); return null; case ISHR: case LSHR: push(new Shr(pop(), pop())); return null; case IUSHR: case LUSHR: push(new Ushr(pop(), pop())); return null; case IAND: case LAND: push(new And(pop(), pop())); return null; case IOR: case LOR: push(new Or(pop(), pop())); return null; case IXOR: case LXOR: push(new Xor(pop(), pop())); return null; case IINC: return local[i1] = new Add(local[i1], new Constant(i2)); // Control and branching // ////////////////////////////////////////////////////////////////////////////// case IFNULL: return new Branch(new Eq(pop(), new Constant(null)), new Label(i1)); case IFNONNULL: return new Branch(new Not(new Eq(pop(), new Constant(null))), new Label(i1)); case IFEQ: return new Branch(new Eq(new Constant(0), pop()), arg); case IFNE: return new Branch(new Not(new Eq(new Constant(0), pop())), arg); case IFLT: return new Branch(new Lt(new Constant(0), pop()), arg); case IFGE: return new Branch(new Not(new Lt(new Constant(0), pop())), arg); case IFGT: return new Branch(new Gt(new Constant(0), pop()), arg); case IFLE: return new Branch(new Not(new Gt(new Constant(0), pop())), arg); case IF_ICMPEQ: return new Branch(new Eq(pop(), pop()), arg); case IF_ICMPNE: return new Branch(new Not(new Eq(pop(), pop())), arg); case IF_ICMPLT: return new Branch(new Lt(pop(), pop()), arg); case IF_ICMPGE: return new Branch(new Not(new Lt(pop(), pop())), arg); case IF_ICMPGT: return new Branch(new Gt(pop(), pop()), arg); case IF_ICMPLE: return new Branch(new Not(new Gt(pop(), pop())), arg); case IF_ACMPEQ: return new Branch(new Eq(pop(), pop()), arg); case IF_ACMPNE: return new Branch(new Not(new Eq(pop(), pop())), arg); case ATHROW: return new Throw(pop()); case GOTO: return new Branch(new Label(i1)); case JSR: return new JSR(new Label(i1)); case RET: return new RET(); case RETURN: return new Return(); case IRETURN: case LRETURN: case FRETURN: case DRETURN: case ARETURN: return new Return(pop()); // Array manipulations // ////////////////////////////////////////////////////////////////////////////// case IALOAD: case LALOAD: case FALOAD: case DALOAD: case AALOAD: case BALOAD: case CALOAD: case SALOAD: return seqPush(new ArrayGet(pop(), pop())); case IASTORE: case LASTORE: case FASTORE: case DASTORE: case AASTORE: case BASTORE: case CASTORE: case SASTORE: return new ArrayPut(pop(), pop(), pop()); // Invocation ////////////////////////////////////////////////////////////////////////////// case INVOKEVIRTUAL: case INVOKESPECIAL: case INVOKESTATIC: case INVOKEINTERFACE: { Type.Class.Method method = (Type.Class.Method) arg; Expr args[] = new Expr[method.getNumArgs()]; for (int i = 0; i < args.length; i++) args[args.length - i - 1] = pop(); Expr ret; switch (op) { case INVOKEVIRTUAL: ret = new InvokeVirtual(method, args, pop()); break; case INVOKEINTERFACE: ret = new InvokeInterface(method, args, pop()); break; case INVOKESPECIAL: ret = new InvokeSpecial(method, args, pop()); break; case INVOKESTATIC: ret = new InvokeStatic(method, args); break; default: throw new Error("should never happen"); } if (ret.getType() != Type.VOID) push(ret); return new Seq(ret); } // Field Access // ////////////////////////////////////////////////////////////////////////////// case GETSTATIC: return seqPush(new Get((Type.Class.Field) arg, null)); case PUTSTATIC: return new Put((Type.Class.Field) arg, pop(), null); case GETFIELD: return seqPush(new Get((Type.Class.Field) arg, pop())); case PUTFIELD: return new Put((Type.Class.Field) arg, pop(), pop()); // Allocation ////////////////////////////////////////////////////////////////////////////// case NEW: push(new New((Type.Class) arg)); return null; case NEWARRAY: { Type base; switch (((Integer) arg).intValue()) { case 4: base = Type.BOOLEAN; break; case 5: base = Type.CHAR; break; case 6: base = Type.FLOAT; break; case 7: base = Type.DOUBLE; break; case 8: base = Type.BYTE; break; case 9: base = Type.SHORT; break; case 10: base = Type.INT; break; case 11: base = Type.LONG; break; default: throw new IllegalStateException("invalid array type"); } return seqPush(new NewArray(base.makeArray(), pop())); } case ANEWARRAY: push(new NewArray(((Type.Ref) arg).makeArray(), pop())); return null; case MULTIANEWARRAY: { MethodGen.MultiANewArray mana = (MethodGen.MultiANewArray) arg; Expr[] dims = new Expr[mana.dims]; for (int i = 0; i < dims.length; i++) dims[i] = pop(); return seqPush(new NewArray(mana.type, dims)); } case ARRAYLENGTH: return seqPush(new ArrayLength(pop())); // Runtime Type information // ////////////////////////////////////////////////////////////////////////////// case CHECKCAST: return seqPush(new Cast(pop(), (Type.Ref) arg)); case INSTANCEOF: push(new InstanceOf(pop(), (Type.Ref) arg)); return null; case LDC: case LDC_W: case LDC2_W: push(new Constant(arg)); return null; case BIPUSH: push(new Constant((Integer) arg)); return null; case SIPUSH: push(new Constant((Integer) arg)); return null; case TABLESWITCH: return new Branch((MethodGen.Switch) arg); case LOOKUPSWITCH: return new Branch((MethodGen.Switch) arg); /* case MONITORENTER: Op.monitorEnter(pop()); case MONITOREXIT: Op.monitorExit(pop()); */ case DUP_X1: throw new Error("unimplemented"); case DUP_X2: throw new Error("unimplemented"); case DUP2_X1: throw new Error("unimplemented"); case DUP2_X2: throw new Error("unimplemented"); case LCMP: throw new Error("unimplemented"); case FCMPL: throw new Error("unimplemented"); case FCMPG: throw new Error("unimplemented"); case DCMPL: throw new Error("unimplemented"); case DCMPG: throw new Error("unimplemented"); case GOTO_W: throw new Error("unimplemented"); case JSR_W: throw new Error("unimplemented"); default: throw new Error("unhandled"); } }
public Type getType() { return method.getReturnType(); }