📄 evaluationsimplifier.java
字号:
newOpcode = InstructionConstants.OP_DUP; } } break; } case InstructionConstants.OP_DUP_X1: { boolean stackEntryPresent0 = isStackEntryNecessaryAfter(dupOffset, 0, false); boolean stackEntryPresent1 = isStackEntryNecessaryAfter(dupOffset, 1, false); boolean stackEntryPresent2 = isStackEntryNecessaryAfter(dupOffset, 2, false); // Should either the original element or the copy be present? if (stackEntryPresent0 || stackEntryPresent2) { present = true; // Should the copy be present? if (stackEntryPresent2) { // Compute the number of elements to be skipped. int skipCount = stackEntryPresent1 ? 1 : 0; // Should the original element be present? if (stackEntryPresent0) { // Copy the original element. newOpcode = (byte)(InstructionConstants.OP_DUP + skipCount); } else if (skipCount == 1) { // Move the original element. newOpcode = InstructionConstants.OP_SWAP; } } } break; } case InstructionConstants.OP_DUP_X2: { boolean stackEntryPresent0 = isStackEntryNecessaryAfter(dupOffset, 0, false); boolean stackEntryPresent1 = isStackEntryNecessaryAfter(dupOffset, 1, false); boolean stackEntryPresent2 = isStackEntryNecessaryAfter(dupOffset, 2, false); boolean stackEntryPresent3 = isStackEntryNecessaryAfter(dupOffset, 3, false); // Should either the original element or the copy be present? if (stackEntryPresent0 || stackEntryPresent3) { present = true; // Should the copy be present? if (stackEntryPresent3) { int skipCount = (stackEntryPresent1 ? 1 : 0) + (stackEntryPresent2 ? 1 : 0); // Should the original element be present? if (stackEntryPresent0) { // Copy the original element. newOpcode = (byte)(InstructionConstants.OP_DUP + skipCount); } else if (skipCount == 1) { // Move the original element. newOpcode = InstructionConstants.OP_SWAP; } else if (skipCount == 2) { // We can't easily move the original element. throw new IllegalArgumentException("Can't handle dup_x2 instruction moving original element across two elements at ["+dupOffset +"]"); } } } break; } case InstructionConstants.OP_DUP2: { boolean stackEntriesPresent01 = isStackEntriesNecessaryAfter(dupOffset, 0, 1, false); boolean stackEntriesPresent23 = isStackEntriesNecessaryAfter(dupOffset, 2, 3, false); // Should either the original element or the copy be present? if (stackEntriesPresent01 || stackEntriesPresent23) { present = true; // Should both the original element and the copy be present? if (stackEntriesPresent01 && stackEntriesPresent23) { newOpcode = InstructionConstants.OP_DUP2; } } break; } case InstructionConstants.OP_DUP2_X1: { boolean stackEntriesPresent01 = isStackEntriesNecessaryAfter(dupOffset, 0, 1, false); boolean stackEntryPresent2 = isStackEntryNecessaryAfter(dupOffset, 2, false); boolean stackEntriesPresent34 = isStackEntriesNecessaryAfter(dupOffset, 3, 4, false); // Should either the original element or the copy be present? if (stackEntriesPresent01 || stackEntriesPresent34) { present = true; // Should the copy be present? if (stackEntriesPresent34) { int skipCount = stackEntryPresent2 ? 1 : 0; // Should the original element be present? if (stackEntriesPresent01) { // Copy the original element. newOpcode = (byte)(InstructionConstants.OP_DUP2 + skipCount); } else if (skipCount > 0) { // We can't easily move the original element. throw new IllegalArgumentException("Can't handle dup2_x1 instruction moving original element across "+skipCount+" elements at ["+dupOffset +"]"); } } } break; } case InstructionConstants.OP_DUP2_X2: { boolean stackEntriesPresent01 = isStackEntriesNecessaryAfter(dupOffset, 0, 1, false); boolean stackEntryPresent2 = isStackEntryNecessaryAfter(dupOffset, 2, false); boolean stackEntryPresent3 = isStackEntryNecessaryAfter(dupOffset, 3, false); boolean stackEntriesPresent45 = isStackEntriesNecessaryAfter(dupOffset, 4, 5, false); // Should either the original element or the copy be present? if (stackEntriesPresent01 || stackEntriesPresent45) { present = true; // Should the copy be present? if (stackEntriesPresent45) { int skipCount = (stackEntryPresent2 ? 1 : 0) + (stackEntryPresent3 ? 1 : 0); // Should the original element be present? if (stackEntriesPresent01) { // Copy the original element. newOpcode = (byte)(InstructionConstants.OP_DUP2 + skipCount); } else if (skipCount > 0) { // We can't easily move the original element. throw new IllegalArgumentException("Can't handle dup2_x2 instruction moving original element across "+skipCount+" elements at ["+dupOffset +"]"); } } } break; } case InstructionConstants.OP_SWAP: { boolean stackEntryPresent0 = isStackEntryNecessaryAfter(dupOffset, 0, false); boolean stackEntryPresent1 = isStackEntryNecessaryAfter(dupOffset, 1, false); // Will either element be present? if (stackEntryPresent0 || stackEntryPresent1) { present = true; // Will both elements be present? if (stackEntryPresent0 && stackEntryPresent1) { newOpcode = InstructionConstants.OP_SWAP; } } break; } } boolean updated = false; // Actually replace the instruction with the new opcode, if any. if (present) { // If this is the first pass, note that the instruction is updated. if (!isNecessary[dupOffset]) { updated = true; // Mark that the instruction is necessary. isNecessary[dupOffset] = true; } if (newOpcode == 0) { // Delete the instruction. codeAttributeEditor.deleteInstruction(dupOffset); if (DEBUG_ANALYSIS) System.out.println(" Marking but deleting instruction "+instruction.toString(dupOffset)); } else if (newOpcode == oldOpcode) { // Leave the instruction unchanged. codeAttributeEditor.undeleteInstruction(dupOffset); if (DEBUG_ANALYSIS) System.out.println(" Marking unchanged instruction "+instruction.toString(dupOffset)); } else { // Replace the instruction. Instruction replacementInstruction = new SimpleInstruction(newOpcode); codeAttributeEditor.replaceInstruction(dupOffset, replacementInstruction); if (DEBUG_ANALYSIS) System.out.println(" Replacing instruction "+instruction.toString(dupOffset)+" by "+replacementInstruction.toString()); } } return updated; } /** * Pops the stack after the given necessary instruction, if it pushes an * entry that is not used at all. * @param clazz the class that is being checked. * @param codeAttribute the code that is being checked. * @param producerOffset the offset of the producer instruction. * @param instruction the producer instruction. */ private void fixPushInstruction(Clazz clazz, CodeAttribute codeAttribute, int producerOffset, Instruction instruction) { int pushCount = instruction.stackPushCount(clazz); if (pushCount > 0) { boolean stackEntryPresent0 = isStackEntryNecessaryAfter(producerOffset, 0, false); if (!stackEntryPresent0) { if (instruction.opcode != InstructionConstants.OP_JSR && instruction.opcode != InstructionConstants.OP_JSR_W) { // Make sure the pushed value is popped again, // right after this instruction. decreaseStackSize(producerOffset, pushCount, false, false); if (DEBUG_ANALYSIS) System.out.println(" Popping unused value right after "+instruction.toString(producerOffset)); } } } } /** * Pops the stack before the given unnecessary instruction, if the stack * contains an entry that it would have popped. * @param clazz the class that is being checked. * @param codeAttribute the code that is being checked. * @param consumerOffset the offset of the consumer instruction. * @param instruction the consumer instruction. */ private void fixPopInstruction(Clazz clazz, CodeAttribute codeAttribute, int consumerOffset, Instruction instruction) { int popCount = instruction.stackPopCount(clazz); if (popCount > 0) { if (partialEvaluator.stackProducerOffsets(consumerOffset).contains(PartialEvaluator.AT_CATCH_ENTRY) || (isStackEntryNecessaryBefore(consumerOffset, 0, false) && !isStackEntryNecessaryBefore(consumerOffset, 0, true))) { // Is the consumer a simple pop or pop2 instruction? byte popOpcode = instruction.opcode; if (popOpcode == InstructionConstants.OP_POP || popOpcode == InstructionConstants.OP_POP2) { if (DEBUG_ANALYSIS) System.out.println(" Popping value again at "+instruction.toString(consumerOffset)); // Simply mark the pop or pop2 instruction. isNecessary[consumerOffset] = true; } else { if (DEBUG_ANALYSIS) System.out.println(" Popping value instead of "+instruction.toString(consumerOffset)); // Make sure the pushed value is popped again, // right before this instruction. decreaseStackSize(consumerOffset, popCount, true, true); } } } } /** * Puts the required push instruction before the given index. The * instruction is marked as necessary. * @param offset the offset of the instruction. * @param computationalType the computational type on the stack, for * push instructions.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -