📄 evaluationsimplifier.java
字号:
decreaseStackSize(consumerOffset, popCount, true, isNotNecessary); } } else if (isAnyNecessary(producerOffsets)) { // Pop the values right after the pushing instructions. if (DEBUG_ANALYSIS) System.out.println(" Popping value somewhere before "+consumerOffset+" (pushed at some of "+producerOffsets.instructionOffsetCount()+" offsets):"); // Go over all stack pushing instructions. int producerCount = producerOffsets.instructionOffsetCount(); for (int producerIndex = 0; producerIndex < producerCount; producerIndex++) { // Has the push instruction been marked? int producerOffset = producerOffsets.instructionOffset(producerIndex); if (producerOffset == PartialEvaluator.AT_METHOD_ENTRY) { Instruction pushInstruction = InstructionFactory.create(codeAttrInfo.code, producerOffset); if (DEBUG_ANALYSIS) System.out.println(" Popping value at start of method"); // Pop it right at the beginning of the method. decreaseStackSize(0, pushInstruction.stackPushCount(classFile), true, false); } else if (isNecessaryProducer(producerOffset)) { // Look at the consumers of this producer. We know // the producer can't be a dup/swap instructions, // so its consumers can be retrieved from the top // stack entry. InstructionOffsetValue topConsumerOffsets = partialEvaluator.stackTopConsumerOffsets(producerOffset, 0); // Check if the consumer has been cleared because // of an unused parameter, or if the producer is // pointing directly to this consumer. // In those cases, we must pop the value. // Otherwise leave it to the fixed intermediary // dup/swap instruction to fix the stack. if (topConsumerOffsets.instructionOffsetCount() == 0 || topConsumerOffsets.contains(consumerOffset)) { if (DEBUG_ANALYSIS) System.out.println(" Popping value right after "+producerOffset+", due to push at "+producerOffset); // Make sure the pushed value is popped again. Instruction pushInstruction = InstructionFactory.create(codeAttrInfo.code, producerOffset); // Pop it right after the instruction that // pushes it. decreaseStackSize(producerOffset, pushInstruction.stackPushCount(classFile), false, false); } } } } } } } /** * Marks the specified instruction if it is a required dup/swap instruction, * replacing it by an appropriate variant if necessary. * @param codeAttrInfo the code that is being checked. * @param offset the offset of the instruction. */ private void fixDupInstruction(CodeAttrInfo codeAttrInfo, int offset) { byte oldOpcode = codeAttrInfo.code[offset]; byte newOpcode = 0; boolean present = false; // Simplify the popping instruction if possible. switch (oldOpcode) { case InstructionConstants.OP_DUP: { boolean stackEntryPresent0 = isStackEntryPresent(offset, 0); boolean stackEntryPresent1 = isStackEntryPresent(offset, 1); // 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) { newOpcode = InstructionConstants.OP_DUP; } } break; } case InstructionConstants.OP_DUP_X1: { boolean stackEntryPresent0 = isStackEntryPresent(offset, 0); boolean stackEntryPresent1 = isStackEntryPresent(offset, 1); boolean stackEntryPresent2 = isStackEntryPresent(offset, 2); // 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 = isStackEntryPresent(offset, 0); boolean stackEntryPresent1 = isStackEntryPresent(offset, 1); boolean stackEntryPresent2 = isStackEntryPresent(offset, 2); boolean stackEntryPresent3 = isStackEntryPresent(offset, 3); // 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"); } } } break; } case InstructionConstants.OP_DUP2: { boolean stackEntriesPresent01 = isStackEntriesPresent(offset, 0, 1); boolean stackEntriesPresent23 = isStackEntriesPresent(offset, 2, 3); // 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 = isStackEntriesPresent(offset, 0, 1); boolean stackEntryPresent2 = isStackEntryPresent(offset, 2); boolean stackEntriesPresent34 = isStackEntriesPresent(offset, 3, 4); // 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"); } } } break; } case InstructionConstants.OP_DUP2_X2: { boolean stackEntriesPresent01 = isStackEntriesPresent(offset, 0, 1); boolean stackEntryPresent2 = isStackEntryPresent(offset, 2); boolean stackEntryPresent3 = isStackEntryPresent(offset, 3); boolean stackEntriesPresent45 = isStackEntriesPresent(offset, 4, 5); // 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"); } } } break; } case InstructionConstants.OP_SWAP: { boolean stackEntryPresent0 = isStackEntryPresent(offset, 0); boolean stackEntryPresent1 = isStackEntryPresent(offset, 1); // Will either element be present? if (stackEntryPresent0 || stackEntryPresent1) { present = true; // Will both elements be present? if (stackEntryPresent0 && stackEntryPresent1) { newOpcode = InstructionConstants.OP_SWAP; } } break; } } // Actually replace the instruction with the new opcode, if any. if (present) { // Mark that the instruction is necessary. isNecessary[offset] = true; if (newOpcode == 0) { // Delete the instruction. codeAttrInfoEditor.deleteInstruction(offset); if (DEBUG_ANALYSIS) System.out.println(" Marking but deleting instruction at ["+offset+"]"); } else if (newOpcode == oldOpcode) { // Leave the instruction unchanged. if (DEBUG_ANALYSIS) System.out.println(" Marking unchanged instruction at ["+offset+"]");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -