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 37 public class PushPopRemover 38 extends SimplifiedVisitor 39 implements InstructionVisitor 40 { 41 private BranchTargetFinder branchTargetFinder; 42 private CodeAttributeEditor codeAttributeEditor; 43 private InstructionVisitor extraInstructionVisitor; 44 45 46 54 public PushPopRemover(BranchTargetFinder branchTargetFinder, 55 CodeAttributeEditor codeAttributeEditor) 56 { 57 this(branchTargetFinder, codeAttributeEditor, null); 58 } 59 60 61 71 public PushPopRemover(BranchTargetFinder branchTargetFinder, 72 CodeAttributeEditor codeAttributeEditor, 73 InstructionVisitor extraInstructionVisitor) 74 { 75 this.branchTargetFinder = branchTargetFinder; 76 this.codeAttributeEditor = codeAttributeEditor; 77 this.extraInstructionVisitor = extraInstructionVisitor; 78 } 79 80 81 83 public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {} 84 85 86 public void visitSimpleInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction) 87 { 88 switch (simpleInstruction.opcode) 89 { 90 case InstructionConstants.OP_ICONST_M1: 91 case InstructionConstants.OP_ICONST_0: 92 case InstructionConstants.OP_ICONST_1: 93 case InstructionConstants.OP_ICONST_2: 94 case InstructionConstants.OP_ICONST_3: 95 case InstructionConstants.OP_ICONST_4: 96 case InstructionConstants.OP_ICONST_5: 97 case InstructionConstants.OP_LCONST_0: 98 case InstructionConstants.OP_LCONST_1: 99 case InstructionConstants.OP_FCONST_0: 100 case InstructionConstants.OP_FCONST_1: 101 case InstructionConstants.OP_FCONST_2: 102 case InstructionConstants.OP_DCONST_0: 103 case InstructionConstants.OP_DCONST_1: 104 105 case InstructionConstants.OP_DUP: 106 case InstructionConstants.OP_DUP2: 107 case InstructionConstants.OP_BIPUSH: 108 case InstructionConstants.OP_SIPUSH: 109 case InstructionConstants.OP_LDC: 110 case InstructionConstants.OP_LDC_W: 111 case InstructionConstants.OP_LDC2_W: 112 deleteWithSubsequentPop(clazz, method, codeAttribute, offset, simpleInstruction); 114 break; 115 } 116 } 117 118 public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction) 119 { 120 if (variableInstruction.isLoad() && 121 variableInstruction.opcode != InstructionConstants.OP_RET) 122 { 123 deleteWithSubsequentPop(clazz, method, codeAttribute, offset, variableInstruction); 125 } 126 } 127 128 129 131 135 private void deleteWithSubsequentPop(Clazz clazz, 136 Method method, 137 CodeAttribute codeAttribute, 138 int offset, 139 Instruction instruction) 140 { 141 boolean isCategory2 = instruction.isCategory2(); 142 143 int nextOffset = offset + instruction.length(offset); 144 145 if (!codeAttributeEditor.isModified(offset) && 146 !codeAttributeEditor.isModified(nextOffset) && 147 !branchTargetFinder.isTarget(nextOffset)) 148 { 149 Instruction nextInstruction = InstructionFactory.create(codeAttribute.code, 150 nextOffset); 151 int nextOpcode = nextInstruction.opcode; 152 if ((nextOpcode == InstructionConstants.OP_POP || 153 nextOpcode == InstructionConstants.OP_POP2) && 154 nextInstruction.isCategory2() == isCategory2) 155 { 156 codeAttributeEditor.deleteInstruction(offset); 158 codeAttributeEditor.deleteInstruction(nextOffset); 159 160 if (extraInstructionVisitor != null) 162 { 163 instruction.accept(clazz, method, codeAttribute, offset, extraInstructionVisitor); 164 } 165 } 166 } 167 } 168 } 169 | Popular Tags |