1 21 package proguard.optimize.info; 22 23 import proguard.classfile.*; 24 import proguard.classfile.attribute.*; 25 import proguard.classfile.constant.*; 26 import proguard.classfile.constant.visitor.ConstantVisitor; 27 import proguard.classfile.instruction.*; 28 import proguard.classfile.instruction.visitor.InstructionVisitor; 29 import proguard.classfile.util.*; 30 import proguard.classfile.visitor.*; 31 32 41 public class SideEffectInstructionChecker 42 extends SimplifiedVisitor 43 implements InstructionVisitor, 44 ConstantVisitor, 45 MemberVisitor 46 { 47 private boolean includeReturnInstructions; 48 49 private boolean hasSideEffects; 51 52 53 public SideEffectInstructionChecker(boolean includeReturnInstructions) 54 { 55 this.includeReturnInstructions = includeReturnInstructions; 56 } 57 58 59 public boolean hasSideEffects(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) 60 { 61 hasSideEffects = false; 62 63 instruction.accept(clazz, method, codeAttribute, offset, this); 64 65 return hasSideEffects; 66 } 67 68 69 71 public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {} 72 73 74 public void visitSimpleInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction) 75 { 76 byte opcode = simpleInstruction.opcode; 77 78 if (opcode == InstructionConstants.OP_IASTORE || 80 opcode == InstructionConstants.OP_LASTORE || 81 opcode == InstructionConstants.OP_FASTORE || 82 opcode == InstructionConstants.OP_DASTORE || 83 opcode == InstructionConstants.OP_AASTORE || 84 opcode == InstructionConstants.OP_BASTORE || 85 opcode == InstructionConstants.OP_CASTORE || 86 opcode == InstructionConstants.OP_SASTORE || 87 opcode == InstructionConstants.OP_ATHROW || 88 opcode == InstructionConstants.OP_MONITORENTER || 89 opcode == InstructionConstants.OP_MONITOREXIT || 90 (includeReturnInstructions && 91 (opcode == InstructionConstants.OP_IRETURN || 92 opcode == InstructionConstants.OP_LRETURN || 93 opcode == InstructionConstants.OP_FRETURN || 94 opcode == InstructionConstants.OP_DRETURN || 95 opcode == InstructionConstants.OP_ARETURN || 96 opcode == InstructionConstants.OP_RETURN))) 97 { 98 hasSideEffects = true; 100 } 101 102 } 103 104 105 public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction) 106 { 107 byte opcode = variableInstruction.opcode; 108 109 if (includeReturnInstructions && 111 opcode == InstructionConstants.OP_RET) 112 { 113 hasSideEffects = true; 114 } 115 } 116 117 118 public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction) 119 { 120 byte opcode = constantInstruction.opcode; 121 122 if (opcode == InstructionConstants.OP_PUTSTATIC || 124 opcode == InstructionConstants.OP_PUTFIELD || 125 opcode == InstructionConstants.OP_INVOKEVIRTUAL || 126 opcode == InstructionConstants.OP_INVOKESPECIAL || 127 opcode == InstructionConstants.OP_INVOKESTATIC || 128 opcode == InstructionConstants.OP_INVOKEINTERFACE) 129 { 130 clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this); 133 } 134 } 135 136 137 public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction) 138 { 139 byte opcode = branchInstruction.opcode; 140 141 if (includeReturnInstructions && 143 (opcode == InstructionConstants.OP_JSR || 144 opcode == InstructionConstants.OP_JSR_W)) 145 { 146 hasSideEffects = true; 147 } 148 } 149 150 151 153 public void visitFieldrefConstant(Clazz clazz, FieldrefConstant fieldrefConstant) 154 { 155 hasSideEffects = true; 157 158 fieldrefConstant.referencedMemberAccept(this); 160 } 161 162 163 public void visitAnyMethodrefConstant(Clazz clazz, RefConstant refConstant) 164 { 165 Member referencedMember = refConstant.referencedMember; 166 167 if (referencedMember == null) 169 { 170 hasSideEffects = true; 172 } 173 else 174 { 175 refConstant.referencedMemberAccept(this); 177 178 if (!hasSideEffects) 180 { 181 Clazz referencedClass = refConstant.referencedClass; 182 Method referencedMethod = (Method)referencedMember; 183 184 referencedClass.methodImplementationsAccept(referencedMethod, 187 false, 188 this); 189 } 190 } 191 } 192 193 194 196 public void visitProgramField(ProgramClass programClass, ProgramField programField) 197 { 198 hasSideEffects = ReadWriteFieldMarker.isRead(programField); 199 } 200 201 202 public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod) 203 { 204 hasSideEffects = hasSideEffects || 205 SideEffectMethodMarker.hasSideEffects(programMethod); 206 } 207 208 209 public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField) 210 { 211 hasSideEffects = true; 212 } 213 214 215 public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod) 216 { 217 hasSideEffects = hasSideEffects || 218 !NoSideEffectMethodMarker.hasNoSideEffects(libraryMethod); 219 } 220 } 221 | Popular Tags |