1 21 package proguard.optimize.peephole; 22 23 import proguard.classfile.instruction.visitor.InstructionVisitor; 24 import proguard.classfile.instruction.*; 25 import proguard.classfile.editor.CodeAttributeEditor; 26 import proguard.classfile.*; 27 import proguard.classfile.util.*; 28 import proguard.classfile.constant.*; 29 import proguard.classfile.constant.visitor.ConstantVisitor; 30 import proguard.classfile.attribute.CodeAttribute; 31 32 40 public class InstructionSequenceReplacer 41 extends SimplifiedVisitor 42 implements InstructionVisitor, 43 ConstantVisitor 44 { 45 private static final boolean DEBUG = false; 46 47 48 private InstructionSequenceMatcher instructionSequenceMatcher; 49 private Instruction[] replacementInstructions; 50 private BranchTargetFinder branchTargetFinder; 51 private CodeAttributeEditor codeAttributeEditor; 52 private InstructionVisitor extraInstructionVisitor; 53 54 private MyReplacementInstructionFactory replacementInstructionFactory = new MyReplacementInstructionFactory(); 55 56 57 69 public InstructionSequenceReplacer(Constant[] patternConstants, 70 Instruction[] patternInstructions, 71 Instruction[] replacementInstructions, 72 BranchTargetFinder branchTargetFinder, 73 CodeAttributeEditor codeAttributeEditor) 74 { 75 this(patternConstants, 76 patternInstructions, 77 replacementInstructions, 78 branchTargetFinder, 79 codeAttributeEditor, 80 null); 81 } 82 83 84 96 public InstructionSequenceReplacer(Constant[] patternConstants, 97 Instruction[] patternInstructions, 98 Instruction[] replacementInstructions, 99 BranchTargetFinder branchTargetFinder, 100 CodeAttributeEditor codeAttributeEditor, 101 InstructionVisitor extraInstructionVisitor) 102 { 103 this.instructionSequenceMatcher = new InstructionSequenceMatcher(patternConstants, patternInstructions); 104 this.replacementInstructions = replacementInstructions; 105 this.branchTargetFinder = branchTargetFinder; 106 this.codeAttributeEditor = codeAttributeEditor; 107 this.extraInstructionVisitor = extraInstructionVisitor; 108 } 109 110 111 113 public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) 114 { 115 if (branchTargetFinder.isTarget(offset) || 118 codeAttributeEditor.isModified(offset)) 119 { 120 instructionSequenceMatcher.reset(); 121 } 122 123 instruction.accept(clazz, method, codeAttribute, offset, instructionSequenceMatcher); 125 126 if (instructionSequenceMatcher.isMatching() && 128 matchedInstructionsUnmodified()) 129 { 130 if (DEBUG) 131 { 132 System.out.println("InstructionSequenceReplacer: ["+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz)+"]"); 133 System.out.println(" Matched:"); 134 for (int index = 0; index < instructionSequenceMatcher.instructionCount(); index++) 135 { 136 int matchedOffset = instructionSequenceMatcher.matchedInstructionOffset(index); 137 System.out.println(" "+InstructionFactory.create(codeAttribute.code, matchedOffset).toString(matchedOffset)); 138 } 139 System.out.println(" Replacement:"); 140 for (int index = 0; index < replacementInstructions.length; index++) 141 { 142 int matchedOffset = instructionSequenceMatcher.matchedInstructionOffset(index); 143 System.out.println(" "+replacementInstructionFactory.create(index).toString(matchedOffset)); 144 } 145 } 146 147 for (int index = 0; index < replacementInstructions.length; index++) 149 { 150 codeAttributeEditor.replaceInstruction(instructionSequenceMatcher.matchedInstructionOffset(index), 151 replacementInstructionFactory.create(index)); 152 } 153 154 for (int index = replacementInstructions.length; index < instructionSequenceMatcher.instructionCount(); index++) 156 { 157 codeAttributeEditor.deleteInstruction(instructionSequenceMatcher.matchedInstructionOffset(index)); 158 } 159 160 if (extraInstructionVisitor != null) 162 { 163 instruction.accept(clazz, 164 method, 165 codeAttribute, 166 offset, 167 extraInstructionVisitor); 168 } 169 } 170 } 171 172 173 175 179 private boolean matchedInstructionsUnmodified() 180 { 181 for (int index = 0; index < instructionSequenceMatcher.instructionCount(); index++) 182 { 183 if (codeAttributeEditor.isModified(instructionSequenceMatcher.matchedInstructionOffset(index))) 184 { 185 return false; 186 } 187 } 188 189 return true; 190 } 191 192 193 197 private class MyReplacementInstructionFactory 198 implements InstructionVisitor 199 { 200 private Instruction replacementInstruction; 201 202 203 207 public Instruction create(int index) 208 { 209 replacementInstructions[index].accept(null, 211 null, 212 null, 213 instructionSequenceMatcher.matchedInstructionOffset(index), 214 this); 215 216 return replacementInstruction.shrink(); 218 } 219 220 221 223 public void visitSimpleInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction) 224 { 225 replacementInstruction = 226 new SimpleInstruction(simpleInstruction.opcode, 227 instructionSequenceMatcher.matchedArgument(simpleInstruction.constant)); 228 } 229 230 231 public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction) 232 { 233 replacementInstruction = 234 new VariableInstruction(variableInstruction.opcode, 235 instructionSequenceMatcher.matchedArgument(variableInstruction.variableIndex), 236 instructionSequenceMatcher.matchedArgument(variableInstruction.constant)); 237 } 238 239 240 public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction) 241 { 242 replacementInstruction = 243 new ConstantInstruction(constantInstruction.opcode, 244 instructionSequenceMatcher.matchedConstantIndex(constantInstruction.constantIndex), 245 instructionSequenceMatcher.matchedArgument(constantInstruction.constant)); 246 } 247 248 249 public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction) 250 { 251 replacementInstruction = 252 new BranchInstruction(branchInstruction.opcode, 253 instructionSequenceMatcher.matchedBranchOffset(offset, 254 branchInstruction.branchOffset)); 255 } 256 257 258 public void visitTableSwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, TableSwitchInstruction tableSwitchInstruction) 259 { 260 replacementInstruction = 261 new TableSwitchInstruction(tableSwitchInstruction.opcode, 262 instructionSequenceMatcher.matchedArgument(tableSwitchInstruction.defaultOffset), 263 instructionSequenceMatcher.matchedArgument(tableSwitchInstruction.lowCase), 264 instructionSequenceMatcher.matchedArgument(tableSwitchInstruction.highCase), 265 instructionSequenceMatcher.matchedJumpOffsets(offset, 266 tableSwitchInstruction.jumpOffsets)); 267 268 } 269 270 271 public void visitLookUpSwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, LookUpSwitchInstruction lookUpSwitchInstruction) 272 { 273 replacementInstruction = 274 new LookUpSwitchInstruction(lookUpSwitchInstruction.opcode, 275 instructionSequenceMatcher.matchedArgument(lookUpSwitchInstruction.defaultOffset), 276 instructionSequenceMatcher.matchedArguments(lookUpSwitchInstruction.cases), 277 instructionSequenceMatcher.matchedJumpOffsets(offset, 278 lookUpSwitchInstruction.jumpOffsets)); 279 } 280 } 281 } 282 | Popular Tags |