FileDocCategorySizeDatePackage
BasicVerifier.javaAPI DocGlassfish v2 API11648Thu Mar 02 11:51:18 GMT 2006oracle.toplink.libraries.asm.tree.analysis

BasicVerifier

public class BasicVerifier extends BasicInterpreter
An extended {@link BasicInterpreter} that checks that bytecode instructions are correctly used.
author
Eric Bruneton
author
Bing Ran

Fields Summary
Constructors Summary
Methods Summary
public ValuebinaryOperation(oracle.toplink.libraries.asm.tree.AbstractInsnNode insn, Value value1, Value value2)

    Value expected1;
    Value expected2;
    switch (insn.getOpcode()) {
      case IALOAD:
      case BALOAD:
      case CALOAD:
      case SALOAD:
        expected1 = newValue(Type.getType("[I"));
        expected2 = BasicValue.INT_VALUE;
        break;
      case LALOAD:
        expected1 = newValue(Type.getType("[J"));
        expected2 = BasicValue.INT_VALUE;
        break;        
      case FALOAD:
        expected1 = newValue(Type.getType("[F"));
        expected2 = BasicValue.INT_VALUE;
        break;
      case DALOAD:
        expected1 = newValue(Type.getType("[D"));
        expected2 = BasicValue.INT_VALUE;
        break;
      case AALOAD:        
        expected1 = newValue(Type.getType("[Ljava/lang/Object;"));
        expected2 = BasicValue.INT_VALUE;
        break;
      case IADD:
      case ISUB:
      case IMUL:
      case IDIV:
      case IREM:
      case ISHL:
      case ISHR:
      case IUSHR:
      case IAND:
      case IOR:
      case IXOR:
      case IF_ICMPEQ:
      case IF_ICMPNE:
      case IF_ICMPLT:
      case IF_ICMPGE:
      case IF_ICMPGT:
      case IF_ICMPLE:
        expected1 = BasicValue.INT_VALUE;
        expected2 = BasicValue.INT_VALUE;
        break;
      case FADD:
      case FSUB:
      case FMUL:
      case FDIV:
      case FREM:
      case FCMPL:
      case FCMPG:
        expected1 = BasicValue.FLOAT_VALUE;
        expected2 = BasicValue.FLOAT_VALUE;
        break;
      case LADD:
      case LSUB:
      case LMUL:
      case LDIV:
      case LREM:
      case LAND:
      case LOR:
      case LXOR:
      case LCMP:
        expected1 = BasicValue.LONG_VALUE;
        expected2 = BasicValue.LONG_VALUE;
        break;
      case LSHL:
      case LSHR:
      case LUSHR:
        expected1 = BasicValue.LONG_VALUE;
        expected2 = BasicValue.INT_VALUE;
        break;
      case DADD:
      case DSUB:
      case DMUL:
      case DDIV:
      case DREM:
      case DCMPL:
      case DCMPG:
        expected1 = BasicValue.DOUBLE_VALUE;
        expected2 = BasicValue.DOUBLE_VALUE;
        break;
      case IF_ACMPEQ:
      case IF_ACMPNE:
        expected1 = BasicValue.REFERENCE_VALUE;
        expected2 = BasicValue.REFERENCE_VALUE;
        break;
      case PUTFIELD:
        FieldInsnNode fin = (FieldInsnNode)insn;
        expected1 = newValue(Type.getType("L" + fin.owner + ";"));
        expected2 = newValue(Type.getType(fin.desc));
        break;
      default:
        throw new RuntimeException("Internal error.");
    }
    if (!isSubTypeOf(value1, expected1)) {
      throw new AnalyzerException("First argument", expected1, value1);
    } else if (!isSubTypeOf(value2, expected2)) {
      throw new AnalyzerException("Second argument", expected2, value2);
    }
    if (insn.getOpcode() == AALOAD) {
      return getElementValue(value1);
    } else {
      return super.binaryOperation(insn, value1, value2);
    }
  
public ValuecopyOperation(oracle.toplink.libraries.asm.tree.AbstractInsnNode insn, Value value)

    Value expected;
    switch (insn.getOpcode()) {
      case ILOAD:
      case ISTORE:
        expected = BasicValue.INT_VALUE;
        break;
      case FLOAD:
      case FSTORE:
        expected = BasicValue.FLOAT_VALUE;
        break;
      case LLOAD:
      case LSTORE:
        expected = BasicValue.LONG_VALUE;
        break;
      case DLOAD:
      case DSTORE:
        expected = BasicValue.DOUBLE_VALUE;
        break;
      case ALOAD:
        if (!((BasicValue)value).isReference()) {
          throw new AnalyzerException(null, "an object reference", value);
        }
        return value;
      case ASTORE:
        if (!((BasicValue)value).isReference() && 
            value != BasicValue.RETURNADDRESS_VALUE)
        {
          throw new AnalyzerException(
            null, "an object reference or a return address", value);
        }
        return value;
      default:
        return value;
    }
    // type is necessarily a primitive type here, 
    // so value must be == to expected value
    if (value != expected) {
      throw new AnalyzerException(null, expected, value);
    }
    return value;
  
protected ValuegetElementValue(Value objectArrayValue)

    return BasicValue.REFERENCE_VALUE;
  
protected booleanisArrayValue(Value value)

    return ((BasicValue)value).isReference();
  
protected booleanisSubTypeOf(Value value, Value expected)

    return value == expected;
  
public ValuenaryOperation(oracle.toplink.libraries.asm.tree.AbstractInsnNode insn, java.util.List values)

    int opcode = insn.getOpcode();
    if (opcode == MULTIANEWARRAY) {
      for (int i = 0; i < values.size(); ++i) {
        if (values.get(i) != BasicValue.INT_VALUE) {
          throw new AnalyzerException(
            null, BasicValue.INT_VALUE, (Value)values.get(i));
        }
      }
    } else {
      int i = 0;
      int j = 0;
      if (opcode != INVOKESTATIC) {
        Type owner = Type.getType("L" + ((MethodInsnNode)insn).owner + ";"); 
        if (!isSubTypeOf((Value)values.get(i++), newValue(owner))) {
          throw new AnalyzerException(
            "Method owner", newValue(owner), (Value)values.get(0));
        }
      }
      Type[] args = Type.getArgumentTypes(((MethodInsnNode)insn).desc);
      while (i < values.size()) {
        Value expected = newValue(args[j++]);
        Value encountered = (Value)values.get(i++);
        if (!isSubTypeOf(encountered, expected)) {
          throw new AnalyzerException("Argument " + j, expected, encountered);
        }
      }
    }
    return super.naryOperation(insn, values);
  
public ValueternaryOperation(oracle.toplink.libraries.asm.tree.AbstractInsnNode insn, Value value1, Value value2, Value value3)

    Value expected1;
    Value expected3;
    switch (insn.getOpcode()) {
      case IASTORE: 
      case BASTORE:
      case CASTORE:
      case SASTORE:
        expected1 = newValue(Type.getType("[I"));
        expected3 = BasicValue.INT_VALUE;
        break;
      case LASTORE:
        expected1 = newValue(Type.getType("[J"));
        expected3 = BasicValue.LONG_VALUE;
        break;
      case FASTORE:
        expected1 = newValue(Type.getType("[F"));
        expected3 = BasicValue.FLOAT_VALUE;
        break;
      case DASTORE:
        expected1 = newValue(Type.getType("[D"));
        expected3 = BasicValue.DOUBLE_VALUE;
        break;
      case AASTORE:
        expected1 = value1;
        expected3 = getElementValue(value1);
        break;   
      default:
        throw new RuntimeException("Internal error.");
    }
    if (!isSubTypeOf(value1, expected1)) {
      throw new AnalyzerException(
        "First argument", "a " + expected1 + " array reference", value1);
    } else if (value2 != BasicValue.INT_VALUE) {
      throw new AnalyzerException(
        "Second argument", BasicValue.INT_VALUE, value2);
    } else if (!isSubTypeOf(value3, expected3)) {
      throw new AnalyzerException("Third argument", expected3, value3);
    }
    return null;
  
public ValueunaryOperation(oracle.toplink.libraries.asm.tree.AbstractInsnNode insn, Value value)

    Value expected;
    switch (insn.getOpcode()) {
      case INEG:
      case IINC:
      case I2F:
      case I2L:
      case I2D:
      case I2B:
      case I2C:
      case I2S:
      case IFEQ:
      case IFNE:
      case IFLT:
      case IFGE:
      case IFGT:
      case IFLE:
      case TABLESWITCH:
      case LOOKUPSWITCH:
      case IRETURN:
      case NEWARRAY:
      case ANEWARRAY:
        expected = BasicValue.INT_VALUE;
        break;
      case FNEG:
      case F2I:
      case F2L:
      case F2D:
      case FRETURN:
        expected = BasicValue.FLOAT_VALUE;
        break;
      case LNEG:
      case L2I:
      case L2F:
      case L2D:
      case LRETURN:
        expected = BasicValue.LONG_VALUE;
        break;
      case DNEG:
      case D2I:
      case D2F:
      case D2L:
      case DRETURN:
        expected = BasicValue.DOUBLE_VALUE;
        break;
      case GETFIELD:
        expected = newValue(Type.getType("L" + ((FieldInsnNode)insn).owner + ";"));
        break;
      case CHECKCAST:
        if (!((BasicValue)value).isReference()) {
          throw new AnalyzerException(null, "an object reference", value);
        }
        return super.unaryOperation(insn, value);
      case ARRAYLENGTH:
        if (!isArrayValue(value)) {
          throw new AnalyzerException(null, "an array reference", value);
        }
        return super.unaryOperation(insn, value);
      case ARETURN:
      case ATHROW:
      case INSTANCEOF:
      case MONITORENTER:
      case MONITOREXIT:
      case IFNULL:
      case IFNONNULL:
        if (!((BasicValue)value).isReference()) {
          throw new AnalyzerException(null, "an object reference", value);
        }
        return super.unaryOperation(insn, value);
      case PUTSTATIC:
        expected = newValue(Type.getType(((FieldInsnNode)insn).desc));
        break;
      default:
        throw new RuntimeException("Internal error.");
    }
    if (!isSubTypeOf(value, expected)) {
      throw new AnalyzerException(null, expected, value);
    }
    return super.unaryOperation(insn, value);