private void checkArrayArgs(MethodNode methodNode, Frame<BasicValue> logMessageFrame, Frame<BasicValue> arraySizeFrame, int lineNumber, MethodInsnNode methodInsn, int messageIndex, int arrayIndex) { BasicValue arraySizeObject = getStackValue(arraySizeFrame, methodInsn, arrayIndex); if (arraySizeObject instanceof ArraySizeBasicValue == false) { wrongUsageCallback.accept(new WrongLoggerUsage(className, methodNode.name, methodInsn.name, lineNumber, "Could not determine size of array")); return; } ArraySizeBasicValue arraySize = (ArraySizeBasicValue) arraySizeObject; PlaceHolderStringBasicValue logMessageLength = checkLogMessageConsistency(methodNode, logMessageFrame, lineNumber, methodInsn, messageIndex, arraySize.minValue); if (logMessageLength == null) { return; } if (arraySize.minValue != arraySize.maxValue) { wrongUsageCallback.accept(new WrongLoggerUsage(className, methodNode.name, methodInsn.name, lineNumber, "Multiple parameter arrays with conflicting sizes")); return; } assert logMessageLength.minValue == logMessageLength.maxValue && arraySize.minValue == arraySize.maxValue; if (logMessageLength.minValue != arraySize.minValue) { wrongUsageCallback.accept(new WrongLoggerUsage(className, methodNode.name, methodInsn.name, lineNumber, "Expected " + logMessageLength.minValue + " arguments but got " + arraySize.minValue)); return; } }
private PlaceHolderStringBasicValue checkLogMessageConsistency(MethodNode methodNode, Frame<BasicValue> logMessageFrame, int lineNumber, MethodInsnNode methodInsn, int messageIndex, int argsSize) { BasicValue logMessageLengthObject = getStackValue(logMessageFrame, methodInsn, messageIndex); if (logMessageLengthObject instanceof PlaceHolderStringBasicValue == false) { if (argsSize > 0) { wrongUsageCallback.accept(new WrongLoggerUsage(className, methodNode.name, methodInsn.name, lineNumber, "First argument must be a string constant so that we can statically ensure proper place holder usage")); } else { // don't check logger usage for logger.warn(someObject) } return null; } PlaceHolderStringBasicValue logMessageLength = (PlaceHolderStringBasicValue) logMessageLengthObject; if (logMessageLength.minValue != logMessageLength.maxValue) { wrongUsageCallback.accept(new WrongLoggerUsage(className, methodNode.name, methodInsn.name, lineNumber, "Multiple log messages with conflicting number of place holders")); return null; } return logMessageLength; }
@Override protected AbstractInsnNode transformTypeInsnNode(MethodNode mn, TypeInsnNode typeNode) { if (frames == null) return typeNode; if (typeNode.getOpcode() == Opcodes.CHECKCAST) { Frame current = frames[mn.instructions.indexOf(typeNode)]; int size = current.getStackSize(); if (current.getStack(size - 1) == BooleanArrayInterpreter.INT_ARRAY) { BooleanTestabilityTransformation.logger.info("Array is of boolean type, changing CHECKCAST to [I"); TypeInsnNode replacement = new TypeInsnNode(Opcodes.CHECKCAST, "[I"); mn.instructions.insertBefore(typeNode, replacement); mn.instructions.remove(typeNode); return replacement; } } return typeNode; }
/** {@inheritDoc} */ @Override public List<Mutation> apply(MethodNode mn, String className, String methodName, BytecodeInstruction instruction, Frame frame) { List<Mutation> mutations = new LinkedList<Mutation>(); JumpInsnNode node = (JumpInsnNode) instruction.getASMNode(); LabelNode target = node.label; // insert mutation into bytecode with conditional JumpInsnNode mutation = new JumpInsnNode(getOpposite(node.getOpcode()), target); // insert mutation into pool Mutation mutationObject = MutationPool.addMutation(className, methodName, NAME, instruction, mutation, Mutation.getDefaultInfectionDistance()); mutations.add(mutationObject); return mutations; }
@Override public boolean merge(final Frame<? extends BasicValue> frame, final Interpreter<BasicValue> interpreter) throws AnalyzerException { if (force) { // uses the current frame return true; } if (frame instanceof ExtendedFrame && ((ExtendedFrame) frame).force) { init(frame); return true; } return super.merge(frame, interpreter); }
@Test public void uninitializedInTheStack() throws Exception { MethodNode mv = new MethodNode(ACC_PUBLIC, "apply", "(Ljava/lang/String;)Ljava/lang/Integer;", null, null); mv.visitTypeInsn(NEW, "java/lang/Integer"); mv.visitInsn(DUP); mv.visitVarInsn(ALOAD, 1); // insn 3 mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Integer", "<init>", "(Ljava/lang/String;)V", false); // insn 4 mv.visitInsn(ARETURN); mv.visitMaxs(3, 2); Frame<BasicValue>[] frames = new FrameAnalyzer().analyze("com/ea/async/Bogus", mv); assertEquals(3, frames[3].getStackSize()); assertTrue(((ExtendedValue) frames[3].getStack(0)).isUninitialized()); assertFalse(((ExtendedValue) frames[4].getStack(0)).isUninitialized()); }
@Test public void uninitializedInTheStackCheckOrder() throws Exception { MethodNode mv = new MethodNode(ACC_PUBLIC, "apply", "(Ljava/lang/String;)Ljava/lang/Integer;", null, null); mv.visitIntInsn(SIPUSH, 99); mv.visitTypeInsn(NEW, "java/lang/Integer"); mv.visitInsn(DUP); mv.visitVarInsn(ALOAD, 1); // insn 4 mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Integer", "<init>", "(Ljava/lang/String;)V", false); // insn 5 mv.visitInsn(SWAP); mv.visitInsn(POP); mv.visitInsn(ARETURN); mv.visitMaxs(4, 2); Frame<BasicValue>[] frames = new FrameAnalyzer().analyze("com/ea/async/Bogus", mv); assertEquals(3, frames[3].getStackSize()); assertTrue(((ExtendedValue) frames[4].getStack(1)).isUninitialized()); assertFalse(((ExtendedValue) frames[5].getStack(1)).isUninitialized()); }
static void printAnalyzerResult(MethodNode method, Analyzer<BasicValue> a, final PrintWriter pw) { Frame<BasicValue>[] frames = a.getFrames(); Textifier t = new Textifier(); TraceMethodVisitor mv = new TraceMethodVisitor(t); pw.println(method.name + method.desc); for (int j = 0; j < method.instructions.size(); ++j) { method.instructions.get(j).accept(mv); StringBuilder sb = new StringBuilder(); Frame<BasicValue> f = frames[j]; if (f == null) { sb.append('?'); } else { for (int k = 0; k < f.getLocals(); ++k) { sb.append(getShortName(f.getLocal(k).toString())) .append(' '); } sb.append(" : "); for (int k = 0; k < f.getStackSize(); ++k) { sb.append(getShortName(f.getStack(k).toString())) .append(' '); } } while (sb.length() < method.maxStack + method.maxLocals + 1) { sb.append(' '); } pw.print(Integer.toString(j + 100000).substring(1)); pw.print(" " + sb + " : " + t.text.get(t.text.size() - 1)); } for (int j = 0; j < method.tryCatchBlocks.size(); ++j) { method.tryCatchBlocks.get(j).accept(mv); pw.print(" " + t.text.get(t.text.size() - 1)); } pw.println(); }
private void checkFixedArityArgs(MethodNode methodNode, Frame<BasicValue> logMessageFrame, int lineNumber, MethodInsnNode methodInsn, int messageIndex, int positionalArgsLength) { PlaceHolderStringBasicValue logMessageLength = checkLogMessageConsistency(methodNode, logMessageFrame, lineNumber, methodInsn, messageIndex, positionalArgsLength); if (logMessageLength == null) { return; } if (logMessageLength.minValue != positionalArgsLength) { wrongUsageCallback.accept(new WrongLoggerUsage(className, methodNode.name, methodInsn.name, lineNumber, "Expected " + logMessageLength.minValue + " arguments but got " + positionalArgsLength)); return; } }
public boolean collectCodeBlocks() { int numIns = mn.instructions.size(); codeBlocks[0] = FrameInfo.FIRST; for(int i=0 ; i<numIns ; i++) { Frame f = frames[i]; if(f != null) { // reachable ? AbstractInsnNode in = mn.instructions.get(i); if(in.getType() == AbstractInsnNode.METHOD_INSN) { MethodInsnNode min = (MethodInsnNode)in; int opcode = min.getOpcode(); if(db.isMethodSuspendable(min.owner, min.name, min.desc, opcode == Opcodes.INVOKEVIRTUAL || opcode == Opcodes.INVOKESTATIC)) { db.log(LogLevel.DEBUG, "Method call at instruction %d to %s#%s%s is suspendable", i, min.owner, min.name, min.desc); FrameInfo fi = addCodeBlock(f, i); splitTryCatch(fi); } else { int blockingId = isBlockingCall(min); if(blockingId >= 0) { int mask = 1 << blockingId; if(!db.isAllowBlocking()) { throw new UnableToInstrumentException("blocking call to " + min.owner + "#" + min.name + min.desc, className, mn.name, mn.desc); } else if((warnedAboutBlocking & mask) == 0) { warnedAboutBlocking |= mask; db.log(LogLevel.WARNING, "Method %s#%s%s contains potentially blocking call to " + min.owner + "#" + min.name + min.desc, className, mn.name, mn.desc); } } } } } } addCodeBlock(null, numIns); return numCodeBlocks > 1; }
private FrameInfo addCodeBlock(Frame f, int end) { if(++numCodeBlocks == codeBlocks.length) { FrameInfo[] newArray = new FrameInfo[numCodeBlocks*2]; System.arraycopy(codeBlocks, 0, newArray, 0, codeBlocks.length); codeBlocks = newArray; } FrameInfo fi = new FrameInfo(f, firstLocal, end, mn.instructions, db); codeBlocks[numCodeBlocks] = fi; return fi; }
private AbstractInsnNode getSource(MethodNode methodNode, Frame<SourceValue>[] frames, AbstractInsnNode now, int... wants) { Frame<SourceValue> currentFrame = frames[methodNode.instructions.indexOf(now)]; SourceValue currentValue; for (int want : wants) if (want == now.getOpcode()) return now; switch (now.getOpcode()) { case ALOAD: { currentValue = currentFrame.getLocal(((VarInsnNode) now).var); break; } case ASTORE: { currentValue = currentFrame.getStack(currentFrame.getStackSize() - 1); break; } case DUP: { currentValue = currentFrame.getStack(currentFrame.getStackSize() - 1); break; } case PUTSTATIC: { currentValue = currentFrame.getStack(currentFrame.getStackSize() - 1); break; } case SWAP: { currentValue = currentFrame.getStack(currentFrame.getStackSize() - 1); break; } default: { oops("Unexpected opcode {}", now.getOpcode()); return null; } } if (currentValue.insns.size() != 1) { oops("Expected 1 source insn, found {}", TransformerHelper.insnsToString(currentValue.insns)); return null; } return getSource(methodNode, frames, currentValue.insns.iterator().next(), wants); }
public boolean isBooleanOnStack(MethodNode mn, AbstractInsnNode node, int position) { int insnPosition = mn.instructions.indexOf(node); if (insnPosition >= currentFrames.length) { logger.info("Trying to access frame out of scope: " + insnPosition + "/" + currentFrames.length); return false; } Frame frame = currentFrames[insnPosition]; return frame.getStack(frame.getStackSize() - 1 - position) == BooleanValueInterpreter.BOOLEAN_VALUE; }
private Frame[] getArrayFrames(MethodNode mn) { try { Analyzer a = new Analyzer(new BooleanArrayInterpreter()); a.analyze(cn.name, mn); return a.getFrames(); } catch (Exception e) { logger.info("[Array] Error during analysis: " + e); return null; } }
/** {@inheritDoc} */ @Override public List<Mutation> apply(MethodNode mn, String className, String methodName, BytecodeInstruction instruction, Frame frame) { numVariable = getNextIndex(mn); List<Mutation> mutations = new LinkedList<Mutation>(); InsnNode node = (InsnNode) instruction.getASMNode(); for (int opcode : getMutations(node.getOpcode())) { InsnNode mutation = new InsnNode(opcode); // insert mutation into pool Mutation mutationObject = MutationPool.addMutation(className, methodName, NAME + " " + getOp(node.getOpcode()) + " -> " + getOp(opcode), instruction, mutation, getInfectionDistance(node.getOpcode(), opcode)); mutations.add(mutationObject); } return mutations; }
/** {@inheritDoc} */ @Override public List<Mutation> apply(MethodNode mn, String className, String methodName, BytecodeInstruction instruction, Frame frame) { List<Mutation> mutations = new LinkedList<Mutation>(); Object value = getValue(instruction.getASMNode()); for (Object replacement : getReplacement(value)) { // insert mutation into bytecode with conditional LdcInsnNode mutation = new LdcInsnNode(replacement); // insert mutation into pool String summary = NAME + " - " + value + " -> " + replacement; if (replacement instanceof String) { summary = summary.replace("*/", "*_/"); } Mutation mutationObject = MutationPool.addMutation(className, methodName, summary, instruction, mutation, Mutation.getDefaultInfectionDistance()); mutations.add(mutationObject); } return mutations; }
private Map<String, InsnList> getLocalReplacementsInc(MethodNode mn, String desc, IincInsnNode node, Frame frame) { Map<String, InsnList> replacements = new HashMap<String, InsnList>(); int otherNum = -1; otherNum = node.var; int currentId = mn.instructions.indexOf(node); for (Object v : mn.localVariables) { LocalVariableNode localVar = (LocalVariableNode) v; int startId = mn.instructions.indexOf(localVar.start); int endId = mn.instructions.indexOf(localVar.end); logger.info("Checking local variable " + localVar.name + " of type " + localVar.desc + " at index " + localVar.index); if (!localVar.desc.equals(desc)) logger.info("- Types do not match: " + localVar.name); if (localVar.index == otherNum) logger.info("- Replacement = original " + localVar.name); if (currentId < startId) logger.info("- Out of scope (start) " + localVar.name); if (currentId > endId) logger.info("- Out of scope (end) " + localVar.name); BasicValue newValue = (BasicValue) frame.getLocal(localVar.index); if (newValue == BasicValue.UNINITIALIZED_VALUE) logger.info("- Not initialized"); if (localVar.desc.equals(desc) && localVar.index != otherNum && currentId >= startId && currentId <= endId && newValue != BasicValue.UNINITIALIZED_VALUE) { logger.info("Adding local variable " + localVar.name + " of type " + localVar.desc + " at index " + localVar.index); InsnList list = new InsnList(); list.add(new IincInsnNode(localVar.index, node.incr)); replacements.put(localVar.name, list); } } return replacements; }
/** {@inheritDoc} */ @Override public List<Mutation> apply(MethodNode mn, String className, String methodName, BytecodeInstruction instruction, Frame frame) { List<Mutation> mutations = new LinkedList<Mutation>(); FieldInsnNode node = (FieldInsnNode) instruction.getASMNode(); Type fieldType = Type.getType(node.desc); // insert mutation into bytecode with conditional InsnList mutation = new InsnList(); logger.debug("Mutation deletefield for statement " + node.name + node.desc); if (node.getOpcode() == Opcodes.GETFIELD) { logger.debug("Deleting source of type " + node.owner); mutation.add(new InsnNode(Opcodes.POP)); } mutation.add(getDefault(fieldType)); // insert mutation into pool Mutation mutationObject = MutationPool.addMutation(className, methodName, NAME + " " + node.name + node.desc, instruction, mutation, getInfectionDistance(node, mutation)); mutations.add(mutationObject); return mutations; }
public ExtendedFrame(final Frame<? extends BasicValue> src) { super(src); if (src instanceof ExtendedFrame) { this.monitors = ((ExtendedFrame) src).monitors; } }
@Override public Frame<BasicValue> init(final Frame<? extends BasicValue> src) { final Frame<BasicValue> frame = super.init(src); if (frame instanceof ExtendedFrame && src instanceof ExtendedFrame) { ((ExtendedFrame) frame).monitors = ((ExtendedFrame) src).monitors; } return frame; }
@Test public void uninitializedInTheLocals() throws Exception { MethodNode mv = new MethodNode(ACC_PUBLIC, "apply", "(Ljava/lang/String;)Ljava/lang/Integer;", null, null); mv.visitIntInsn(SIPUSH, 99); mv.visitTypeInsn(NEW, "java/lang/Integer"); mv.visitInsn(DUP); mv.visitVarInsn(ASTORE, 2); mv.visitInsn(DUP); mv.visitVarInsn(ALOAD, 1); // insn 6 mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Integer", "<init>", "(Ljava/lang/String;)V", false); // insn 7 mv.visitInsn(SWAP); mv.visitInsn(POP); mv.visitInsn(ARETURN); mv.visitMaxs(4, 3); Frame<BasicValue>[] frames = new FrameAnalyzer().analyze("com/ea/async/Bogus", mv); assertEquals(3, frames[3].getStackSize()); // local is now initialized assertTrue(((ExtendedValue) frames[6].getStack(1)).isUninitialized()); assertTrue(((ExtendedValue) frames[6].getLocal(2)).isUninitialized()); // local is now initialized assertFalse(((ExtendedValue) frames[7].getStack(1)).isUninitialized()); assertFalse(((ExtendedValue) frames[7].getLocal(2)).isUninitialized()); }
@Test public void branchAnalysisWithFrames() throws AnalyzerException { MethodNode mv = new MethodNode(ACC_PUBLIC, "apply", "(I)Ljava/lang/Object;", null, null); mv.visitCode(); mv.visitInsn(ICONST_1); mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false); mv.visitVarInsn(ASTORE, 2); mv.visitVarInsn(ILOAD, 1); mv.visitInsn(ICONST_3); Label l0 = new Label(); mv.visitJumpInsn(IF_ICMPNE, l0); mv.visitLdcInsn(new Double("2.0")); mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", false); mv.visitVarInsn(ASTORE, 2); mv.visitLabel(l0); mv.visitFrame(F_FULL, 3, new Object[]{ "com/ea/async/Bogus", INTEGER, "java/lang/Number" }, 0, new Object[0]); mv.visitVarInsn(ALOAD, 2); mv.visitInsn(ARETURN); mv.visitMaxs(2, 3); mv.visitEnd(); Frame<BasicValue>[] frames = new FrameAnalyzer().analyze("com/ea/async/Bogus", mv); // when the frameNode is not used by the analyzer this will return java/lang/Object Frame<BasicValue> frame = frames[frames.length - 1]; assertEquals("com/ea/async/Bogus", frame.getLocal(0).getType().getInternalName()); assertEquals("I", frame.getLocal(1).getType().toString()); assertEquals("java/lang/Number", frame.getLocal(2).getType().getInternalName()); }
SuspendContinuationPoint( Integer lineNumber, MethodInsnNode invokeInstruction, Frame<BasicValue> frame) { // lineNumber is null if it doesn't exist Validate.notNull(invokeInstruction); // stateModifierMethod is null if it doesn't exist Validate.notNull(frame); this.lineNumber = lineNumber; this.invokeInstruction = invokeInstruction; this.continueExecutionLabel = new LabelNode(); this.frame = frame; }
TryCatchInvokeContinuationPoint( Integer lineNumber, MethodInsnNode invokeInstruction, Frame<BasicValue> frame) { // lineNumber is null if it doesn't exist Validate.notNull(invokeInstruction); Validate.notNull(frame); this.lineNumber = lineNumber; this.invokeInstruction = invokeInstruction; this.continueExecutionLabel = new LabelNode(); this.exceptionExecutionLabel = new LabelNode(); this.tryCatchBlock = new TryCatchBlockNode(null, null, null, null); this.frame = frame; }
SynchronizationPoint( InsnNode monitorInstruction, Frame<BasicValue> frame) { Validate.notNull(monitorInstruction); Validate.notNull(frame); Validate.isTrue(monitorInstruction.getOpcode() == Opcodes.MONITORENTER || monitorInstruction.getOpcode() == Opcodes.MONITOREXIT); this.monitorInstruction = monitorInstruction; this.frame = frame; }
NormalInvokeContinuationPoint( Integer lineNumber, MethodInsnNode invokeInstruction, Frame<BasicValue> frame) { // lineNumber is null if it doesn't exist Validate.notNull(invokeInstruction); // stateModifierMethod is null if it doesn't exist Validate.notNull(frame); this.lineNumber = lineNumber; this.invokeInstruction = invokeInstruction; this.continueExecutionLabel = new LabelNode(); this.frame = frame; }
public Frame init(Frame frame) { super.init(frame); if (frame instanceof MonitoringFrame) { monitored = new LinkedList<Integer>(MonitoringFrame.class.cast(frame).monitored); } else { monitored = new LinkedList<Integer>(); } return this; }
public void visitEnd() { checkCallSites(); if (instructions.size() == 0 || labels.size() == 0) { accept(mv); return; } this.stackRecorderVar = maxLocals; try { moveNew(); analyzer = new Analyzer(new FastClassVerifier()) { @Override protected Frame newFrame(final int nLocals, final int nStack) { return new MonitoringFrame(nLocals, nStack); } @Override protected Frame newFrame(final Frame src) { return new MonitoringFrame(src); } }; analyzer.analyze(className, this); accept(new ContinuableMethodVisitor(this)); } catch (final AnalyzerException ex) { throw new RuntimeException(ex); } }
public void visitEnd() { if (instructions.size() == 0 || labels.size() == 0) { accept(mv); return; } this.stackRecorderVar = maxLocals; try { moveNew(); analyzer = new Analyzer(new FastClassVerifier()) { @Override protected Frame newFrame(final int nLocals, final int nStack) { return new MonitoringFrame(nLocals, nStack); } @Override protected Frame newFrame(final Frame src) { return new MonitoringFrame(src); } }; analyzer.analyze(className, this); accept(new ContinuableMethodVisitor(this)); } catch (final AnalyzerException ex) { throw new RuntimeException(ex); } }
static void printAnalyzerResult(MethodNode method, Analyzer<BasicValue> a, final PrintWriter pw) { Frame<BasicValue>[] frames = a.getFrames(); Textifier t = new Textifier(); TraceMethodVisitor mv = new TraceMethodVisitor(t); pw.println(method.name + method.desc); for (int j = 0; j < method.instructions.size(); ++j) { method.instructions.get(j).accept(mv); StringBuffer s = new StringBuffer(); Frame<BasicValue> f = frames[j]; if (f == null) { s.append('?'); } else { for (int k = 0; k < f.getLocals(); ++k) { s.append(getShortName(f.getLocal(k).toString())) .append(' '); } s.append(" : "); for (int k = 0; k < f.getStackSize(); ++k) { s.append(getShortName(f.getStack(k).toString())) .append(' '); } } while (s.length() < method.maxStack + method.maxLocals + 1) { s.append(' '); } pw.print(Integer.toString(j + 100000).substring(1)); pw.print(" " + s + " : " + t.text.get(t.text.size() - 1)); } for (int j = 0; j < method.tryCatchBlocks.size(); ++j) { method.tryCatchBlocks.get(j).accept(mv); pw.print(" " + t.text.get(t.text.size() - 1)); } pw.println(); }
private InsnList procAtCallSite(final ProcInstance processor) throws InvalidContextUsageException { final Frame <SourceValue> frame = info.getSourceFrame (weavingLoc); final InsnList result = new InsnList(); for (final ProcMethodInstance pmi : processor.getMethods ()) { final Code code = pmi.getCode ().clone (); final int index = pmi.getArgPos (); final int total = pmi.getArgsCount (); final Type type = pmi.getArgType ().getASMType (); final InsnList insns = code.getInstructions (); rewriteArgumentContextCalls (index, total, type, insns); // Duplicate call site arguments and store them into local vars. final SourceValue source = FrameHelper.getStackByIndex (frame, total - 1 - index); for (final AbstractInsnNode argLoadInsn : source.insns) { // TRICK: the value has to be set properly because // method code will be not adjusted by fixLocalIndex method.instructions.insert (argLoadInsn, AsmHelper.storeVar (type, method.maxLocals + maxLocals)); method.instructions.insert (argLoadInsn, new InsnNode (type.getSize () == 2 ? Opcodes.DUP2 : Opcodes.DUP)); } __shiftLocalSlots (maxLocals, insns); maxLocals = __calcMaxLocals (maxLocals + type.getSize(), insns); result.add (insns); method.tryCatchBlocks.addAll (code.getTryCatchBlocks ()); } return result; }
private void tryRemoveAllocation(InsnList ilist, AbstractInsnNode next, Map<AbstractInsnNode, Frame<SourceValue>> frames) { if (next.getOpcode() != Opcodes.DUP) { return; } // TODO LB: iterate over a copy unless we are sure an iterator is OK for (AbstractInsnNode instr : ilist.toArray()) { if (instr.getOpcode() == Opcodes.INVOKESPECIAL) { Type[] args = Type .getArgumentTypes(((MethodInsnNode) instr).desc); Frame<SourceValue> frame = frames.get(instr); Set<AbstractInsnNode> sources = FrameHelper.getStackByIndex( frame, args.length).insns; if (sources.contains(next)) { for (Type arg : args) { ilist.insert(instr, new InsnNode(arg.getSize() == 2 ? Opcodes.POP2 : Opcodes.POP)); } ilist.remove(instr); } } } ilist.remove(next); }
public boolean evaluate() { ilist.add(new InsnNode(Opcodes.RETURN)); Analyzer<ConstValue> constAnalyzer = new Analyzer<ConstValue>( ConstInterpreter.getInstance()); Map<AbstractInsnNode, Frame<ConstValue>> frames = FrameHelper .createMapping(constAnalyzer, PartialEvaluator.class.getName(), method); boolean isOptimized = conditionalReduction(frames); isOptimized |= replaceLoadWithLDC(frames); boolean removed; do { removed = false; removed |= removeDeadStore(); removed |= removePop(); } while (removed); isOptimized |= removed; isOptimized |= removeUnusedJump(); isOptimized |= removeUnusedHandler(); ilist.remove(ilist.getLast()); return isOptimized; }