📄 evaluationsimplifier.java
字号:
} } } } return nextOffset; } /** * Marks the branch instructions of straddling branches, if they straddle * some code that has been marked. * @param index the offset of the branch origin or branch target. * @param branchOffsets the offsets of the straddling branch targets * or branch origins. * @param isPointingToTargets <code>true</code> if the above offsets are * branch targets, <code>false</code> if they * are branch origins. * @param lowestNecessaryOffset the lowest offset of all instructions marked * so far. * @param nextOffset the offset of the instruction to be investigated * next. * @return the updated offset of the instruction to be investigated next. * It is always greater than or equal the original offset, because * instructions are investigated starting at the highest index. */ private int markStraddlingBranches(int index, InstructionOffsetValue branchOffsets, boolean isPointingToTargets, int lowestNecessaryOffset, int nextOffset) { if (branchOffsets != null) { // Loop over all branch origins. int branchCount = branchOffsets.instructionOffsetCount(); for (int branchIndex = 0; branchIndex < branchCount; branchIndex++) { // Is the branch straddling any necessary instructions? int branch = branchOffsets.instructionOffset(branchIndex); // Is the offset pointing to a branch origin or to a branch target? nextOffset = isPointingToTargets ? markStraddlingBranch(index, branch, lowestNecessaryOffset, nextOffset) : markStraddlingBranch(branch, index, lowestNecessaryOffset, nextOffset); } } return nextOffset; } /** * Marks the given branch instruction, if it straddles some code that has * been marked. * @param branchOrigin the branch origin. * @param branchTarget the branch target. * @param lowestNecessaryOffset the lowest offset of all instructions marked * so far. * @param nextOffset the offset of the instruction to be investigated * next. * @return the updated offset of the instruction to be investigated next. * It is always greater than or equal the original offset, because * instructions are investigated starting at the highest index. */ private int markStraddlingBranch(int branchOrigin, int branchTarget, int lowestNecessaryOffset, int nextOffset) { // Has the branch origin been marked yet, and is it straddling the // lowest necessary instruction? if (!isNecessary[branchOrigin] && isStraddlingBranch(branchOrigin, branchTarget, lowestNecessaryOffset)) { if (DEBUG_ANALYSIS) System.out.print("["+branchOrigin+"->"+branchTarget+"]"); // Mark the branch origin. isNecessary[branchOrigin] = true; // Restart at the branch origin if it has a higher offset. if (nextOffset < branchOrigin) { if (DEBUG_ANALYSIS) System.out.print("!"); nextOffset = branchOrigin; } } return nextOffset; } /** * Marks and simplifies the branch instructions of straddling branches, * if they straddle some code that has been marked. * @param branchOrigin the branch origin. * @param branchTargets the branch targets. * @param lowestNecessaryOffset the lowest offset of all instructions marked * so far. * @param nextOffset the offset of the instruction to be investigated * next. * @return the updated offset of the instruction to be investigated next. * It is always greater than or equal the original offset, because * instructions are investigated starting at the highest index. */ private int markAndSimplifyStraddlingBranches(int branchOrigin, InstructionOffsetValue branchTargets, int lowestNecessaryOffset, int nextOffset) { if (branchTargets != null && !isNecessary[branchOrigin]) { // Loop over all branch targets. int branchCount = branchTargets.instructionOffsetCount(); if (branchCount > 0) { for (int branchIndex = 0; branchIndex < branchCount; branchIndex++) { // Is the branch straddling any necessary instructions? int branchTarget = branchTargets.instructionOffset(branchIndex); if (!isStraddlingBranch(branchOrigin, branchTarget, lowestNecessaryOffset)) { return nextOffset; } } nextOffset = markAndSimplifyStraddlingBranch(branchOrigin, branchTargets.instructionOffset(0), lowestNecessaryOffset, nextOffset); } } return nextOffset; } /** * Marks and simplifies the branch instructions of straddling branches, * if they straddle some code that has been marked. * @param branchOrigins the branch origins. * @param branchTarget the branch target. * @param lowestNecessaryOffset the lowest offset of all instructions marked * so far. * @param nextOffset the offset of the instruction to be investigated * next. * @return the updated offset of the instruction to be investigated next. * It is always greater than or equal the original offset, because * instructions are investigated starting at the highest index. */ private int markAndSimplifyStraddlingBranches(InstructionOffsetValue branchOrigins, int branchTarget, int lowestNecessaryOffset, int nextOffset) { if (branchOrigins != null) { // Loop over all branch origins. int branchCount = branchOrigins.instructionOffsetCount(); for (int branchIndex = 0; branchIndex < branchCount; branchIndex++) { // Is the branch straddling any necessary instructions? int branchOrigin = branchOrigins.instructionOffset(branchIndex); nextOffset = markAndSimplifyStraddlingBranch(branchOrigin, branchTarget, lowestNecessaryOffset, nextOffset); } } return nextOffset; } /** * Marks and simplifies the given branch instruction, if it straddles some * code that has been marked. * @param branchOrigin the branch origin. * @param branchTarget the branch target. * @param lowestNecessaryOffset the lowest offset of all instructions marked * so far. * @param nextOffset the offset of the instruction to be investigated * next. * @return the updated offset of the instruction to be investigated next. * It is always greater than or equal the original offset, because * instructions are investigated starting at the highest index. */ private int markAndSimplifyStraddlingBranch(int branchOrigin, int branchTarget, int lowestNecessaryOffset, int nextOffset) { // Has the branch origin been marked yet, and is it straddling the // lowest necessary instruction? if (!isNecessary[branchOrigin] && isStraddlingBranch(branchOrigin, branchTarget, lowestNecessaryOffset)) { if (DEBUG_ANALYSIS) System.out.print("["+branchOrigin+"->"+branchTarget+"]"); // Mark the branch origin. isNecessary[branchOrigin] = true; // Replace the branch instruction by a simple branch instrucion. Instruction replacementInstruction = new BranchInstruction(InstructionConstants.OP_GOTO_W, branchTarget - branchOrigin).shrink(); codeAttrInfoEditor.replaceInstruction(branchOrigin, replacementInstruction); // Restart at the branch origin if it has a higher offset. if (nextOffset < branchOrigin) { if (DEBUG_ANALYSIS) System.out.print("!"); nextOffset = branchOrigin; } } return nextOffset; } /** * Returns whether the given branch straddling some code that has been marked. * @param branchOrigin the branch origin. * @param branchTarget the branch target. * @param lowestNecessaryOffset the lowest offset of all instructions marked * so far. */ private boolean isStraddlingBranch(int branchOrigin, int branchTarget, int lowestNecessaryOffset) { return branchOrigin <= lowestNecessaryOffset ^ branchTarget <= lowestNecessaryOffset; } /** * Inserts pop instructions where necessary, in order to make sure the * stack is consistent at the given index. * @param classFile the class file that is being checked. * @param codeAttrInfo the code that is being checked. * @param consumerOffset the offset of the consumer instruction. */ private void fixStackConsistency(ClassFile classFile, CodeAttrInfo codeAttrInfo, int consumerOffset) { // See if we have any values pushed on the stack that we aren't using. InstructionOffsetValue producerOffsets = partialEvaluator.unusedProducerOffsets(consumerOffset); // This includes all values if the popping instruction isn't necessary at all. boolean isNotNecessary = !isNecessaryConsumer(consumerOffset); if (isNotNecessary) { producerOffsets = producerOffsets.generalize(partialEvaluator.stackProducerOffsets(consumerOffset)).instructionOffsetValue(); } // Do we have any pushing instructions? if (producerOffsets.instructionOffsetCount() > 0) { // Is this instruction really popping any values? // Note that method invocations have their original pop counts, // including any unused parameters. Instruction popInstruction = InstructionFactory.create(codeAttrInfo.code, consumerOffset); int popCount = popInstruction.stackPopCount(classFile); if (popCount > 0) { // Can we pop all values at the popping instruction? if (isNotNecessary && popCount <= 6 && isAllNecessary(producerOffsets)) { // Is the popping instruction a simple pop or pop2 instruction? byte popOpcode = popInstruction.opcode; if (popOpcode == InstructionConstants.OP_POP || popOpcode == InstructionConstants.OP_POP2) { if (DEBUG_ANALYSIS) System.out.println(" Popping value again at "+popInstruction.toString(consumerOffset)+" (pushed at all "+producerOffsets.instructionOffsetCount()+" offsets)"); // Simply mark the pop or pop2 instruction. isNecessary[consumerOffset] = true; } else { if (DEBUG_ANALYSIS) System.out.println(" Popping value instead of "+popInstruction.toString(consumerOffset)+" (pushed at all "+producerOffsets.instructionOffsetCount()+" offsets)"); // Make sure the pushed value is popped again, // right before this instruction.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -