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); } }