Beispiel #1
0
 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();
 }
Beispiel #2
0
  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");
    }
  }
Beispiel #3
0
 public Type getType() {
   return method.getReturnType();
 }