📄 evaluationsimplifier.java
字号:
} } return nextOffset; } /** * Marks the instruction at the given offset. * @param producerOffset the offsets of the producer to be marked. * @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 markProducer(int producerOffset, int nextOffset) { if (producerOffset > PartialEvaluator.AT_METHOD_ENTRY && !isNecessary[producerOffset]) { if (DEBUG_ANALYSIS) System.out.print("["+producerOffset +"]"); // Mark it. isNecessary[producerOffset] = true; // Restart at this instruction if it has a higher offset. if (nextOffset < producerOffset) { if (DEBUG_ANALYSIS) System.out.print("!"); nextOffset = producerOffset; } } 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(); codeAttributeEditor.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; } /** * Marks the specified instruction if it is a required dup/swap instruction, * replacing it by an appropriate variant if necessary. * @param clazz the class that is being checked. * @param codeAttribute the code that is being checked. * @param dupOffset the offset of the dup/swap instruction. * @param instruction the dup/swap instruction. * @return whether the instruction is updated. */ private boolean fixDupInstruction(Clazz clazz, CodeAttribute codeAttribute, int dupOffset, Instruction instruction) { byte oldOpcode = instruction.opcode; byte newOpcode = 0; boolean present = false; // Simplify the popping instruction if possible. switch (oldOpcode) { case InstructionConstants.OP_DUP: { boolean stackEntryPresent0 = isStackEntryNecessaryAfter(dupOffset, 0, false); boolean stackEntryPresent1 = isStackEntryNecessaryAfter(dupOffset, 1, false); // Should either the original element or the copy be present? if (stackEntryPresent0 || stackEntryPresent1) { present = true; // Should both the original element and the copy be present? if (stackEntryPresent0 && stackEntryPresent1) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -