public TaggedValue analyze() throws AnalyzerException {
    modifiedAsmAnalyzer = new ModifiedASMAnalyzer(this);

    // FOR DEBUGGING
    //		final Printer printer = new Textifier();
    //		final TraceMethodVisitor mp = new TraceMethodVisitor(printer);
    //		System.out.println(methodNode.name + " " + methodNode.desc);
    //		Iterator<AbstractInsnNode> it = methodNode.instructions.iterator();
    //		while (it.hasNext()) {
    //			it.next().accept(mp);
    //			StringWriter sw = new StringWriter();
    //			printer.print(new PrintWriter(sw));
    //			printer.getText().clear();
    //			System.out.println(sw.toString());
    //		}
    modifiedAsmAnalyzer.analyze(owner, methodNode);
    return mergeReturnValues(returnValues);
  }
  @Override
  public BasicValue unaryOperation(AbstractInsnNode insn, BasicValue value)
      throws AnalyzerException {
    switch (insn.getOpcode()) {
        // modify jump instructions if we can assume that the hasNext operation will always
        // be true at the first call
      case IFEQ:
        if (isTagged(value) && tagged(value).isIteratorTrueAssumption()) {
          modifiedAsmAnalyzer.requestIFEQLoopModification();
        }
        return super.unaryOperation(insn, value);
      case IFNE:
        if (isTagged(value) && tagged(value).isIteratorTrueAssumption()) {
          modifiedAsmAnalyzer.requestIFNELoopModification();
        }
        return super.unaryOperation(insn, value);

      case CHECKCAST:
        return value;
      case PUTSTATIC:
        analyzer.handlePutStatic();
        return super.unaryOperation(insn, value);
      case GETFIELD:
        final FieldInsnNode field = (FieldInsnNode) insn;
        // skip untagged values
        if (!isTagged(value)) {
          return super.unaryOperation(insn, value);
        }
        final TaggedValue taggedValue = (TaggedValue) value;

        // inputs are atomic, a GETFIELD results in undefined state
        if (taggedValue.isInput()) {
          return super.unaryOperation(insn, value);
        }
        // access of input container field
        // or access of a KNOWN UDF instance variable
        else if (taggedValue.canContainFields() && taggedValue.containerContains(field.name)) {
          final TaggedValue tv = taggedValue.getContainerMapping().get(field.name);
          if (tv != null) {
            return tv;
          }
        }
        // access of a yet UNKNOWN UDF instance variable
        else if (taggedValue.isThis() && !taggedValue.containerContains(field.name)) {
          final TaggedValue tv = new TaggedValue(Type.getType(field.desc));
          taggedValue.addContainerMapping(field.name, tv, currentFrame);
          return tv;
        }
        // access of a yet unknown container, mark it as a container
        else if (taggedValue.isRegular()) {
          taggedValue.setTag(Tag.CONTAINER);
          final TaggedValue tv = new TaggedValue(Type.getType(field.desc));
          taggedValue.addContainerMapping(field.name, tv, currentFrame);
          return tv;
        }
        return super.unaryOperation(insn, value);
      case IINC:
        // modification of a local variable or input
        if (isTagged(value) && (tagged(value).isIntConstant() || tagged(value).isInput())) {
          tagged(value).makeRegular();
        }
        return super.unaryOperation(insn, value);
      default:
        return super.unaryOperation(insn, value);
    }
  }