1 21 package proguard.optimize.peephole; 22 23 import proguard.classfile.*; 24 import proguard.classfile.attribute.CodeAttribute; 25 import proguard.classfile.editor.CodeAttributeEditor; 26 import proguard.classfile.instruction.*; 27 import proguard.classfile.instruction.visitor.InstructionVisitor; 28 import proguard.classfile.util.SimplifiedVisitor; 29 30 36 public class StoreLoadReplacer 37 extends SimplifiedVisitor 38 implements InstructionVisitor 39 { 40 private Instruction dupInstruction = new SimpleInstruction(InstructionConstants.OP_DUP); 42 private Instruction dup2Instruction = new SimpleInstruction(InstructionConstants.OP_DUP2); 43 44 private BranchTargetFinder branchTargetFinder; 45 private CodeAttributeEditor codeAttributeEditor; 46 private InstructionVisitor extraInstructionVisitor; 47 48 49 57 public StoreLoadReplacer(BranchTargetFinder branchTargetFinder, 58 CodeAttributeEditor codeAttributeEditor) 59 { 60 this(branchTargetFinder, codeAttributeEditor, null); 61 } 62 63 64 74 public StoreLoadReplacer(BranchTargetFinder branchTargetFinder, 75 CodeAttributeEditor codeAttributeEditor, 76 InstructionVisitor extraInstructionVisitor) 77 { 78 this.branchTargetFinder = branchTargetFinder; 79 this.codeAttributeEditor = codeAttributeEditor; 80 this.extraInstructionVisitor = extraInstructionVisitor; 81 } 82 83 84 86 public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {} 87 88 89 public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction) 90 { 91 if (!variableInstruction.isLoad() && 93 variableInstruction.opcode != InstructionConstants.OP_IINC) 94 { 95 byte opcode = variableInstruction.opcode; 96 int variableIndex = variableInstruction.variableIndex; 97 98 int nextOffset = offset + variableInstruction.length(offset); 99 100 if (!codeAttributeEditor.isModified(offset) && 101 !codeAttributeEditor.isModified(nextOffset) && 102 !branchTargetFinder.isTarget(nextOffset)) 103 { 104 Instruction nextInstruction = InstructionFactory.create(codeAttribute.code, 106 nextOffset); 107 108 if (nextInstruction instanceof VariableInstruction) 109 { 110 variableInstruction = (VariableInstruction)nextInstruction; 111 if (variableInstruction.isLoad() && 112 variableInstruction.opcode != InstructionConstants.OP_RET && 113 variableInstruction.variableIndex == variableIndex) 114 { 115 Instruction matchingDupInstruction = variableInstruction.isCategory2() ? 117 dup2Instruction : 118 dupInstruction; 119 120 codeAttributeEditor.replaceInstruction(offset, 121 matchingDupInstruction); 122 123 Instruction storeInstruction = 125 new VariableInstruction(opcode, 126 variableInstruction.variableIndex).shrink(); 127 128 codeAttributeEditor.replaceInstruction(nextOffset, 129 storeInstruction); 130 131 if (extraInstructionVisitor != null) 133 { 134 extraInstructionVisitor.visitVariableInstruction(clazz, method, codeAttribute, offset, variableInstruction); 135 } 136 } 137 } 138 } 139 } 140 } 141 } 142 | Popular Tags |