1 21 package proguard.evaluation; 22 23 import proguard.classfile.util.*; 24 import proguard.classfile.constant.visitor.ConstantVisitor; 25 import proguard.classfile.constant.*; 26 import proguard.classfile.visitor.MemberVisitor; 27 import proguard.classfile.*; 28 import proguard.classfile.instruction.*; 29 import proguard.classfile.attribute.CodeAttribute; 30 import proguard.evaluation.value.*; 31 32 39 public class BasicInvocationUnit 40 extends SimplifiedVisitor 41 implements InvocationUnit, 42 ConstantVisitor, 43 MemberVisitor 44 { 45 private ValueFactory valueFactory = new ValueFactory(); 46 47 private boolean isStatic; 49 private boolean isLoad; 50 private Stack stack; 51 private Clazz returnTypeClass; 52 53 54 57 public void enterMethod(Clazz clazz, Method method, Variables variables) 58 { 59 String descriptor = method.getDescriptor(clazz); 60 61 boolean isStatic = 63 (method.getAccessFlags() & ClassConstants.INTERNAL_ACC_STATIC) != 0; 64 65 int parameterSize = ClassUtil.internalMethodParameterSize(descriptor); 67 if (!isStatic) 68 { 69 parameterSize++; 70 } 71 72 variables.reset(parameterSize); 74 75 InternalTypeEnumeration internalTypeEnumeration = 77 new InternalTypeEnumeration(descriptor); 78 79 int parameterIndex = 0; 80 int variableIndex = 0; 81 82 if (!isStatic) 84 { 85 Value value = getMethodParameterValue(clazz, 87 method, 88 parameterIndex++, 89 ClassUtil.internalTypeFromClassName(clazz.getName()), 90 clazz); 91 92 variables.store(variableIndex++, value); 94 } 95 96 Clazz[] referencedClasses = ((ProgramMethod)method).referencedClasses; 97 int referencedClassIndex = 0; 98 99 while (internalTypeEnumeration.hasMoreTypes()) 101 { 102 String type = internalTypeEnumeration.nextType(); 103 104 Clazz referencedClass = referencedClasses != null && 105 ClassUtil.isInternalClassType(type) ? 106 referencedClasses[referencedClassIndex++] : 107 null; 108 109 Value value = getMethodParameterValue(clazz, 111 method, 112 parameterIndex++, 113 type, 114 referencedClass); 115 116 variables.store(variableIndex++, value); 118 119 if (value.isCategory2()) 121 { 122 variableIndex++; 123 } 124 } 125 } 126 127 128 131 public void exitMethod(Clazz clazz, Method method, Value returnValue) 132 { 133 setMethodReturnValue(clazz, method, returnValue); 134 } 135 136 137 141 public void invokeMember(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction, Stack stack) 142 { 143 int constantIndex = constantInstruction.constantIndex; 144 145 switch (constantInstruction.opcode) 146 { 147 case InstructionConstants.OP_GETSTATIC: 148 isStatic = true; 149 isLoad = true; 150 break; 151 152 case InstructionConstants.OP_PUTSTATIC: 153 isStatic = true; 154 isLoad = false; 155 break; 156 157 case InstructionConstants.OP_GETFIELD: 158 isStatic = false; 159 isLoad = true; 160 break; 161 162 case InstructionConstants.OP_PUTFIELD: 163 isStatic = false; 164 isLoad = false; 165 break; 166 167 case InstructionConstants.OP_INVOKESTATIC: 168 isStatic = true; 169 break; 170 171 case InstructionConstants.OP_INVOKEVIRTUAL: 172 case InstructionConstants.OP_INVOKESPECIAL: 173 case InstructionConstants.OP_INVOKEINTERFACE: 174 isStatic = false; 175 break; 176 } 177 178 this.stack = stack; 180 clazz.constantPoolEntryAccept(constantIndex, this); 181 this.stack = null; 182 } 183 184 185 187 public void visitFieldrefConstant(Clazz clazz, FieldrefConstant fieldrefConstant) 188 { 189 if (!isLoad) 191 { 192 setFieldValue(clazz, fieldrefConstant, stack.pop()); 193 } 194 195 if (!isStatic) 197 { 198 setFieldClassValue(clazz, fieldrefConstant, stack.apop()); 199 } 200 201 if (isLoad) 203 { 204 String type = fieldrefConstant.getType(clazz); 205 206 stack.push(getFieldValue(clazz, fieldrefConstant, type)); 207 } 208 } 209 210 211 public void visitAnyMethodrefConstant(Clazz clazz, RefConstant methodrefConstant) 212 { 213 String type = methodrefConstant.getType(clazz); 214 215 int parameterCount = ClassUtil.internalMethodParameterCount(type); 217 if (!isStatic) 218 { 219 parameterCount++; 220 } 221 222 for (int parameterIndex = parameterCount-1; parameterIndex >= 0; parameterIndex--) 224 { 225 setMethodParameterValue(clazz, methodrefConstant, parameterIndex, stack.pop()); 226 } 227 228 String returnType = ClassUtil.internalMethodReturnType(type); 231 if (returnType.charAt(0) != ClassConstants.INTERNAL_TYPE_VOID) 232 { 233 stack.push(getMethodReturnValue(clazz, methodrefConstant, returnType)); 234 } 235 } 236 237 238 protected void setFieldClassValue(Clazz clazz, 239 RefConstant refConstant, 240 ReferenceValue value) 241 { 242 } 244 245 246 protected Value getFieldClassValue(Clazz clazz, 247 RefConstant refConstant, 248 String type) 249 { 250 returnTypeClass = null; 252 refConstant.referencedMemberAccept(this); 253 254 return valueFactory.createValue(type, 255 returnTypeClass, 256 true); 257 } 258 259 260 protected void setFieldValue(Clazz clazz, 261 RefConstant refConstant, 262 Value value) 263 { 264 } 266 267 268 protected Value getFieldValue(Clazz clazz, 269 RefConstant refConstant, 270 String type) 271 { 272 returnTypeClass = null; 274 refConstant.referencedMemberAccept(this); 275 276 return valueFactory.createValue(type, 277 returnTypeClass, 278 true); 279 } 280 281 282 protected void setMethodParameterValue(Clazz clazz, 283 RefConstant refConstant, 284 int parameterIndex, 285 Value value) 286 { 287 } 289 290 291 protected Value getMethodParameterValue(Clazz clazz, 292 Method method, 293 int parameterIndex, 294 String type, 295 Clazz referencedClass) 296 { 297 return valueFactory.createValue(type, referencedClass, true); 298 } 299 300 301 protected void setMethodReturnValue(Clazz clazz, 302 Method method, 303 Value value) 304 { 305 } 307 308 309 protected Value getMethodReturnValue(Clazz clazz, 310 RefConstant refConstant, 311 String type) 312 { 313 returnTypeClass = null; 315 refConstant.referencedMemberAccept(this); 316 317 return valueFactory.createValue(type, 318 returnTypeClass, 319 true); 320 } 321 322 323 325 public void visitProgramField(ProgramClass programClass, ProgramField programField) 326 { 327 returnTypeClass = programField.referencedClass; 328 } 329 330 331 public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod) 332 { 333 Clazz[] referencedClasses = programMethod.referencedClasses; 334 if (referencedClasses != null) 335 { 336 returnTypeClass = referencedClasses[referencedClasses.length - 1]; 337 } 338 } 339 340 341 public void visitLibraryMember(LibraryClass libraryClass, LibraryMember libraryMember) 342 { 343 } 345 } 346
| Popular Tags
|