/** * Creates a new LivenessAnalyzer. */ public LivenessAnalyzer() { this(new PartialEvaluator()); }
/** * Deletes the reference popping instruction at the given offset, if * it is at the start of a subroutine that doesn't return or a subroutine * that is only called from one place. */ private void deleteReferencePopInstruction(Clazz clazz, int offset, Instruction instruction) { if (partialEvaluator.isSubroutineStart(offset) && (!partialEvaluator.isSubroutineReturning(offset) || partialEvaluator.branchOrigins(offset).instructionOffsetCount() == 1)) { if (DEBUG) System.out.println(" Deleting store of subroutine return address "+instruction.toString(offset)); // A reference value can only be specific if it is null. codeAttributeEditor.deleteInstruction(offset); } }
/** * Returns the instruction offsets to which the given instruction offset * branches in the most recently analyzed code attribute. */ public InstructionOffsetValue branchTargets(int instructionOffset) { return partialEvaluator.branchTargets(instructionOffset); }
/** * Evaluates the instruction block and the exception handlers covering the * given instruction range in the given code. */ private void evaluateInstructionBlockAndExceptionHandlers(Clazz clazz, Method method, CodeAttribute codeAttribute, TracedVariables variables, TracedStack stack, int startOffset, int endOffset) { evaluateInstructionBlock(clazz, method, codeAttribute, variables, stack, startOffset); evaluateExceptionHandlers(clazz, method, codeAttribute, startOffset, endOffset); }
new PartialEvaluator(this); subroutinePartialEvaluator.initializeArrays(codeAttribute); subroutinePartialEvaluator.evaluateInstructionBlockAndExceptionHandlers(clazz, method, codeAttribute, generalize(subroutinePartialEvaluator, 0, codeAttribute.u4codeLength);
subroutinePartialEvaluator = new PartialEvaluator(this); subroutinePartialEvaluator.initializeVariables(clazz, method, codeAttribute, subroutinePartialEvaluator.evaluateInstructionBlockAndExceptionHandlers(clazz, method, codeAttribute, generalize(subroutinePartialEvaluator, 0, codeAttribute.u4codeLength);
partialEvaluator.visitCodeAttribute(clazz, method, codeAttribute); if (partialEvaluator.isTraced(offset)) InstructionOffsetValue branchTargets = partialEvaluator.branchTargets(offset); if (branchTargets != null) checkAgain |= offset < maxOffset(partialEvaluator.branchOrigins(offset)); if (partialEvaluator.isTraced(offset)) Value value = partialEvaluator.getVariablesBefore(offset).getValue(variableIndex); if (value != null && value.isCategory2()) Value value = partialEvaluator.getVariablesAfter(offset).getValue(variableIndex); if (value != null && value.isCategory2())
partialEvaluator.visitCodeAttribute(clazz, method, codeAttribute); if (partialEvaluator.isTraced(offset)) if (partialEvaluator.isExceptionHandler(offset)) if (partialEvaluator.isCreation(offset)) else if (partialEvaluator.isInitializer(offset)) partialEvaluator.branchTargets(offset);
partialEvaluator.visitCodeAttribute(clazz, method, codeAttribute); simplePartialEvaluator.visitCodeAttribute(clazz, method, codeAttribute); partialEvaluator.tracedInstructionFilter(parameterUsageMarker)); partialEvaluator.tracedInstructionFilter(initialUsageMarker)); if (partialEvaluator.isTraced(offset)) partialEvaluator.branchTargets(offset), true); partialEvaluator.branchOrigins(offset), false); if (partialEvaluator.isTraced(offset)) partialEvaluator.branchTargets(offset), true); partialEvaluator.branchOrigins(offset), false); if (partialEvaluator.isTraced(offset) && !isInstructionNecessary(offset)) partialEvaluator.branchTargets(offset), true);
/** * Replaces the given 'jsr' instruction by a simpler branch instruction, * if it jumps to a subroutine that doesn't return or a subroutine that * is only called from one place. */ private void replaceJsrInstruction(Clazz clazz, int offset, BranchInstruction branchInstruction) { // Is the subroutine ever returning? int subroutineStart = offset + branchInstruction.branchOffset; if (!partialEvaluator.isSubroutineReturning(subroutineStart) || partialEvaluator.branchOrigins(subroutineStart).instructionOffsetCount() == 1) { // All 'jsr' instructions to this subroutine can be replaced // by unconditional branch instructions. replaceBranchInstruction(clazz, offset, branchInstruction); } else if (!partialEvaluator.isTraced(offset + branchInstruction.length(offset))) { // We have to make sure the instruction after this 'jsr' // instruction is valid, even if it is never reached. replaceByInfiniteLoop(clazz, offset + branchInstruction.length(offset), branchInstruction); } }
pushInstructionBlock(new TracedVariables(variables), new TracedStack(stack), branchTargets.instructionOffset(index)); evaluateSubroutine(clazz, method, codeAttribute, pushCallingInstructionBlock(new TracedVariables(variables), new TracedStack(stack), instructionOffset);
partialEvaluator.visitCodeAttribute(clazz, method, codeAttribute); if (partialEvaluator.isTraced(offset)) int superInitializationOffset = partialEvaluator.superInitializationOffset(); if (superInitializationOffset != PartialEvaluator.NONE) if (partialEvaluator.isTraced(offset)) if (partialEvaluator.isTraced(offset)) partialEvaluator.branchTargets(offset), true); partialEvaluator.branchOrigins(offset), false); if (partialEvaluator.isTraced(offset) && !isInstructionNecessary(offset)) int variableIndex = partialEvaluator.initializedVariable(offset); if (variableIndex >= 0 && isVariableInitializationNecessary(clazz, if (partialEvaluator.isTraced(offset)) partialEvaluator.branchTargets(offset), true);
if (mayThrowExceptions(clazz, method, codeAttribute, startPC, endPC)) generalizeVariables(startPC, endPC, evaluateAllCode, evaluateInstructionBlock(clazz, method, codeAttribute,
initializeArrays(codeAttribute); initializeParameters(clazz, method, codeAttribute, variables); evaluateInstructionBlockAndExceptionHandlers(clazz, method, codeAttribute,
if (isTraced(startPC, endPC)) generalizeVariables(startPC, endPC, evaluateAllCode, evaluateInstructionBlock(clazz, method, codeAttribute,
/** * 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 (partialEvaluator.isTraced(offset) && !isInstructionNecessary(offset) && isAnyLargerThan(partialEvaluator.branchTargets(offset), instructionOffset2)) { return true; } } return false; }
evaluateSingleInstructionBlock(clazz, method, codeAttribute, (MyInstructionBlock)instructionBlockStack.pop(); evaluateSingleInstructionBlock(clazz, method, codeAttribute,
initializeVariables(clazz, method, codeAttribute, variables, stack); evaluateInstructionBlockAndExceptionHandlers(clazz, method, codeAttribute,
partialEvaluator.visitCodeAttribute(clazz, method, codeAttribute); if (partialEvaluator.isTraced(offset)) InstructionOffsetValue branchTargets = partialEvaluator.branchTargets(offset); if (branchTargets != null) InstructionOffsetValue branchOrigins = partialEvaluator.branchOrigins(offset); if (branchOrigins != null && offset < branchOrigins.maximumValue()) if (partialEvaluator.isTraced(offset)) Value value = partialEvaluator.getVariablesBefore(offset).getValue(variableIndex); if (value != null && value.isCategory2()) Value value = partialEvaluator.getVariablesAfter(offset).getValue(variableIndex); if (value != null && value.isCategory2())
partialEvaluator.visitCodeAttribute(clazz, method, codeAttribute); if (partialEvaluator.isTraced(offset)) if (partialEvaluator.isExceptionHandler(offset)) if (partialEvaluator.isCreation(offset)) else if (partialEvaluator.isInitializer(offset)) partialEvaluator.branchTargets(offset);