1 21 package proguard.optimize.peephole; 22 23 import proguard.classfile.*; 24 import proguard.classfile.attribute.*; 25 import proguard.classfile.attribute.visitor.*; 26 import proguard.classfile.instruction.*; 27 import proguard.classfile.instruction.visitor.InstructionVisitor; 28 import proguard.classfile.util.SimplifiedVisitor; 29 30 36 public class ReachableCodeMarker 37 extends SimplifiedVisitor 38 implements AttributeVisitor, 39 InstructionVisitor, 40 ExceptionInfoVisitor 41 { 42 private boolean[] isReachable = new boolean[ClassConstants.TYPICAL_CODE_LENGTH]; 43 44 private boolean next; 45 private boolean evaluateExceptions; 46 47 48 52 public boolean isReachable(int offset) 53 { 54 return isReachable[offset]; 55 } 56 57 58 62 public boolean isReachable(int startOffset, int endOffset) 63 { 64 for (int offset = startOffset; offset < endOffset; offset++) 66 { 67 if (isReachable[offset]) 68 { 69 return true; 70 } 71 } 72 73 return false; 74 } 75 76 77 79 public void visitAnyAttribute(Clazz clazz, Attribute attribute) {} 80 81 82 public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute) 83 { 84 int codeLength = codeAttribute.u4codeLength; 86 if (isReachable.length < codeLength) 87 { 88 isReachable = new boolean[codeLength]; 90 } 91 else 92 { 93 for (int index = 0; index < codeLength; index++) 95 { 96 isReachable[index] = false; 97 } 98 } 99 100 markCode(clazz, method, codeAttribute, 0); 102 103 do 105 { 106 evaluateExceptions = false; 107 108 codeAttribute.exceptionsAccept(clazz, method, this); 109 } 110 while (evaluateExceptions); 111 } 112 113 114 116 public void visitSimpleInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction) 117 { 118 byte opcode = simpleInstruction.opcode; 119 if (opcode == InstructionConstants.OP_IRETURN || 120 opcode == InstructionConstants.OP_LRETURN || 121 opcode == InstructionConstants.OP_FRETURN || 122 opcode == InstructionConstants.OP_DRETURN || 123 opcode == InstructionConstants.OP_ARETURN || 124 opcode == InstructionConstants.OP_RETURN || 125 opcode == InstructionConstants.OP_ATHROW) 126 { 127 next = false; 128 } 129 } 130 131 132 public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction) 133 { 134 } 135 136 137 public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction) 138 { 139 if (variableInstruction.opcode == InstructionConstants.OP_RET) 140 { 141 next = false; 142 } 143 } 144 145 146 public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction) 147 { 148 markBranchTarget(clazz, 150 method, 151 codeAttribute, 152 offset + branchInstruction.branchOffset); 153 154 byte opcode = branchInstruction.opcode; 155 if (opcode == InstructionConstants.OP_GOTO || 156 opcode == InstructionConstants.OP_GOTO_W) 157 { 158 next = false; 159 } 160 } 161 162 163 public void visitAnySwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SwitchInstruction switchInstruction) 164 { 165 markBranchTarget(clazz, 167 method, 168 codeAttribute, 169 offset + switchInstruction.defaultOffset); 170 171 markBranchTargets(clazz, 173 method, 174 codeAttribute, 175 offset, 176 switchInstruction.jumpOffsets); 177 178 next = false; 179 } 180 181 182 184 public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo) 185 { 186 if (!isReachable(exceptionInfo.u2handlerPC) && 188 isReachable(exceptionInfo.u2startPC, exceptionInfo.u2endPC)) 189 { 190 markCode(clazz, method, codeAttribute, exceptionInfo.u2handlerPC); 191 192 evaluateExceptions = true; 193 } 194 } 195 196 197 199 203 private void markBranchTargets(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, int[] jumpOffsets) 204 { 205 for (int index = 0; index < jumpOffsets.length; index++) 206 { 207 markCode(clazz, method, codeAttribute, offset + jumpOffsets[index]); 208 } 209 } 210 211 212 215 private void markBranchTarget(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset) 216 { 217 boolean oldNext = next; 218 219 markCode(clazz, method, codeAttribute, offset); 220 221 next = oldNext; 222 } 223 224 225 228 private void markCode(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset) 229 { 230 boolean oldNext = next; 231 232 byte[] code = codeAttribute.code; 233 234 while (!isReachable[offset]) 237 { 238 Instruction instruction = InstructionFactory.create(code, offset); 240 241 isReachable[offset] = true; 243 244 next = true; 247 248 instruction.accept(clazz, method, codeAttribute, offset, this); 250 251 if (!next) 253 { 254 break; 255 } 256 257 offset += instruction.length(offset); 259 } 260 261 next = oldNext; 262 } 263 } 264 | Popular Tags |