/** * Creates a new EvaluationShrinker. * @param partialEvaluator the partial evaluator that will * analyze the code. * @param runPartialEvaluator specifies whether the partial * evaluator should be run for each * method, or if some other class is * already doing this. * @param extraDeletedInstructionVisitor an optional extra visitor for all * deleted instructions. * @param extraAddedInstructionVisitor an optional extra visitor for all * added instructions. */ public EvaluationShrinker(PartialEvaluator partialEvaluator, boolean runPartialEvaluator, InstructionVisitor extraDeletedInstructionVisitor, InstructionVisitor extraAddedInstructionVisitor) { this(new InstructionUsageMarker(partialEvaluator, runPartialEvaluator), true, extraDeletedInstructionVisitor, extraAddedInstructionVisitor); }
/** * Returns whether any traced but unnecessary instruction between the two * given offsets is branching over the second given offset. */ private boolean isAnyUnnecessaryInstructionBranchingOver(int instructionOffset1, int instructionOffset2) { for (int offset = instructionOffset1; offset < instructionOffset2; offset++) { // Is it a traced but unmarked straddling branch? if (instructionUsageMarker.isTraced(offset) && !instructionUsageMarker.isInstructionNecessary(offset) && isAnyLargerThan(instructionUsageMarker.branchTargets(offset), instructionOffset2)) { return true; } } return false; }
private void markStraddlingBranch(int instructionOffsetStart, int instructionOffsetEnd, int branchOrigin, int branchTarget) { if (!isInstructionNecessary(branchOrigin) && isAnyInstructionNecessary(instructionOffsetStart, instructionOffsetEnd)) { if (DEBUG) System.out.print("["+branchOrigin+"->"+branchTarget+"]"); // Mark the branch instruction. markInstruction(branchOrigin); } }
/** * Marks that an extra push/pop instruction is required at the given * offset, if the current instruction at that offset is unused. * @param instructionOffset the offset of the instruction. */ private void markExtraPushPopInstruction(int instructionOffset) { if (!isInstructionNecessary(instructionOffset) && !isExtraPushPopInstructionNecessary(instructionOffset)) { if (DEBUG) System.out.print(instructionOffset+","); extraPushPopInstructionsNecessary[instructionOffset] = true; if (maxMarkedOffset < instructionOffset) { maxMarkedOffset = instructionOffset; } } }
if (!isInstructionNecessary(producerOffset)) if (isVariableInitialization(producerOffset, variableIndex)) markInstruction(producerOffset); markVariableInitializersBefore(producerOffset, variableIndex, visitedOffsets);
public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) if (instructionUsageMarker.isInstructionNecessary(offset)) instructionUsageMarker.getStackBefore(offset); instructionUsageMarker.isStackEntryUnwantedBefore( offset, stackIndex); boolean stackEntryPresentBefore = instructionUsageMarker.isStackEntryPresentBefore( offset, stackIndex); instructionUsageMarker.getStackAfter(offset); if (!instructionUsageMarker.isStackEntryNecessaryAfter(offset, stackIndex)) else if (instructionUsageMarker.isExtraPushPopInstructionNecessary(offset)) instructionUsageMarker.getStackBefore(offset); if (instructionUsageMarker.isStackEntryPresentBefore(offset, stackIndex)) instructionUsageMarker.getStackAfter(offset); if (instructionUsageMarker.isStackEntryNecessaryAfter(offset, stackIndex))
boolean stackEntriesPresent01 = instructionUsageMarker.isStackEntriesPresentBefore(instructionOffset, topBefore, topBefore - 1); boolean stackEntryPresent2 = instructionUsageMarker.isStackEntryPresentBefore( instructionOffset, topBefore - 2); boolean stackEntriesNecessary01 = instructionUsageMarker.isStackEntriesNecessaryAfter(instructionOffset, topAfter, topAfter - 1); boolean stackEntryNecessary2 = instructionUsageMarker.isStackEntryNecessaryAfter( instructionOffset, topAfter - 2); boolean stackEntriesNecessary34 = instructionUsageMarker.isStackEntriesNecessaryAfter(instructionOffset, topAfter - 3, topAfter - 4);
initializeNecessary(codeAttribute); if (isInstructionNecessary(offset)) markReverseDependencies(offset); markStraddlingBranches(offset, partialEvaluator.branchTargets(offset), true); markStraddlingBranches(offset, partialEvaluator.branchOrigins(offset), false); necessaryInstructionFilter( variableInitializationMarker)); markStraddlingBranches(offset, partialEvaluator.branchTargets(offset), true); markStraddlingBranches(offset, partialEvaluator.branchOrigins(offset), false); !isInstructionNecessary(offset)) markStraddlingBranches(offset, partialEvaluator.branchTargets(offset),
public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction) { if (instructionUsageMarker.isInstructionNecessary(offset)) { if (branchInstruction.stackPopCount(clazz) > 0 && !instructionUsageMarker.isStackEntryPresentBefore(offset, instructionUsageMarker.getStackBefore(offset).size() - 1)) { // Replace the branch instruction by a simple goto. Instruction replacementInstruction = new BranchInstruction(InstructionConstants.OP_GOTO, branchInstruction.branchOffset); codeAttributeEditor.replaceInstruction(offset, replacementInstruction); if (DEBUG) System.out.println(" Replacing branch instruction "+branchInstruction.toString(offset)+" by "+replacementInstruction.toString()); } } else { visitAnyInstruction(clazz, method, codeAttribute, offset, branchInstruction); } }
instructionUsageMarker.visitCodeAttribute(clazz, method, codeAttribute); instructionUsageMarker.necessaryInstructionFilter(true, staticInvocationFixer)); instructionUsageMarker.tracedInstructionFilter(true, instructionUsageMarker.necessaryInstructionFilter(false, backwardBranchFixer))); instructionUsageMarker.necessaryInstructionFilter(true, nonReturningSubroutineFixer)); instructionUsageMarker.tracedInstructionFilter(true, stackConsistencyFixer)); instructionUsageMarker.necessaryInstructionFilter(false, instructionDeleter)); InstructionOffsetValue branchTargets = instructionUsageMarker.branchTargets(offset); if (branchTargets != null)
public void visitSimpleInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction) if (instructionUsageMarker.isInstructionNecessary(offset) && isDupOrSwap(simpleInstruction)) int topBefore = instructionUsageMarker.getStackBefore(offset).size() - 1; int topAfter = instructionUsageMarker.getStackAfter(offset).size() - 1;
/** * Returns whether the instruction at the given offset should be * visited, depending on whether it is necessary or not. */ private boolean shouldVisit(int offset) { return isInstructionNecessary(offset) == necessary; } }
new InstructionUsageMarker(partialEvaluator, false); instructionUsageMarker, new AllInstructionVisitor( instructionUsageMarker.necessaryInstructionFilter( new MultiInstructionVisitor( readWriteFieldMarker,
public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) { // Is it a traced but unmarked backward branch, without an unmarked // straddling forward branch? Note that this is still a heuristic. if (isAllSmallerThanOrEqual(instructionUsageMarker.branchTargets(offset), offset) && !isAnyUnnecessaryInstructionBranchingOver(lastNecessaryInstructionOffset(offset), offset)) { replaceByInfiniteLoop(clazz, offset); if (DEBUG) System.out.println(" Setting infinite loop instead of "+instruction.toString(offset)); } }
/** * Returns whether the specified stack entry before the given offset is * present. * @param instructionOffset the offset of the stack entry to be checked. * @param stackIndex the index of the stack entry to be checked * (counting from the bottom). */ public boolean isStackEntryPresentBefore(int instructionOffset, int stackIndex) { TracedStack tracedStack = partialEvaluator.getStackBefore(instructionOffset); InstructionOffsetValue producerOffsets = tracedStack.getBottomProducerValue(stackIndex).instructionOffsetValue(); return isAnyStackEntryNecessaryAfter(producerOffsets, stackIndex); }
public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) if (instructionUsageMarker.isInstructionNecessary(offset)) instructionUsageMarker.getStackBefore(offset); instructionUsageMarker.isStackEntryUnwantedBefore( offset, stackIndex); boolean stackEntryPresentBefore = instructionUsageMarker.isStackEntryPresentBefore( offset, stackIndex); instructionUsageMarker.getStackAfter(offset); if (!instructionUsageMarker.isStackEntryNecessaryAfter(offset, stackIndex)) else if (instructionUsageMarker.isExtraPushPopInstructionNecessary(offset)) instructionUsageMarker.getStackBefore(offset); if (instructionUsageMarker.isStackEntryPresentBefore(offset, stackIndex)) instructionUsageMarker.getStackAfter(offset); if (instructionUsageMarker.isStackEntryNecessaryAfter(offset, stackIndex))
boolean stackEntriesPresent01 = instructionUsageMarker.isStackEntriesPresentBefore(instructionOffset, topBefore, topBefore - 1); boolean stackEntryPresent2 = instructionUsageMarker.isStackEntryPresentBefore( instructionOffset, topBefore - 2); boolean stackEntriesNecessary01 = instructionUsageMarker.isStackEntriesNecessaryAfter(instructionOffset, topAfter, topAfter - 1); boolean stackEntryNecessary2 = instructionUsageMarker.isStackEntryNecessaryAfter( instructionOffset, topAfter - 2); boolean stackEntriesNecessary34 = instructionUsageMarker.isStackEntriesNecessaryAfter(instructionOffset, topAfter - 3, topAfter - 4);
initializeNecessary(codeAttribute); if (isInstructionNecessary(offset)) markReverseDependencies(offset); markStraddlingBranches(offset, partialEvaluator.branchTargets(offset), true); markStraddlingBranches(offset, partialEvaluator.branchOrigins(offset), false); necessaryInstructionFilter( variableInitializationMarker)); markStraddlingBranches(offset, partialEvaluator.branchTargets(offset), true); markStraddlingBranches(offset, partialEvaluator.branchOrigins(offset), false); !isInstructionNecessary(offset)) markStraddlingBranches(offset, partialEvaluator.branchTargets(offset),
public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction) { if (instructionUsageMarker.isInstructionNecessary(offset)) { if (branchInstruction.stackPopCount(clazz) > 0 && !instructionUsageMarker.isStackEntryPresentBefore(offset, instructionUsageMarker.getStackBefore(offset).size() - 1)) { // Replace the branch instruction by a simple goto. Instruction replacementInstruction = new BranchInstruction(InstructionConstants.OP_GOTO, branchInstruction.branchOffset); codeAttributeEditor.replaceInstruction(offset, replacementInstruction); if (DEBUG) System.out.println(" Replacing branch instruction "+branchInstruction.toString(offset)+" by "+replacementInstruction.toString()); } } else { visitAnyInstruction(clazz, method, codeAttribute, offset, branchInstruction); } }
if (!isInstructionNecessary(producerOffset)) if (isVariableInitialization(producerOffset, variableIndex)) markInstruction(producerOffset); markVariableInitializersBefore(producerOffset, variableIndex, visitedOffsets);