1b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato/* 2b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * ProGuard -- shrinking, optimization, obfuscation, and preverification 3b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * of Java bytecode. 4b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 5b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu) 6b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 7b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * This program is free software; you can redistribute it and/or modify it 8b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * under the terms of the GNU General Public License as published by the Free 9b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Software Foundation; either version 2 of the License, or (at your option) 10b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * any later version. 11b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 12b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * This program is distributed in the hope that it will be useful, but WITHOUT 13b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 15b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * more details. 16b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 17b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * You should have received a copy of the GNU General Public License along 18b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * with this program; if not, write to the Free Software Foundation, Inc., 19b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 21b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratopackage proguard.optimize; 22b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 23b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.*; 24b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.attribute.*; 25b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.attribute.annotation.*; 26b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.attribute.visitor.AttributeVisitor; 27b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.editor.ConstantPoolEditor; 28b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.util.*; 29b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.visitor.MemberVisitor; 30b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.optimize.info.*; 31b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.optimize.peephole.VariableShrinker; 32b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 33b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato/** 34b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * This MemberVisitor removes unused parameters in the descriptors of the 35b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * methods that it visits. 36b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 37b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @see ParameterUsageMarker 38b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @see VariableUsageMarker 39b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @see VariableShrinker 40b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @author Eric Lafortune 41b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 42b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratopublic class MethodDescriptorShrinker 43b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoextends SimplifiedVisitor 44b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimplements MemberVisitor, 45b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato AttributeVisitor 46b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato{ 47b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private static final boolean DEBUG = false; 48b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 49b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 50b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private final MemberVisitor extraMemberVisitor; 51b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 52b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 53b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 54b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Creates a new MethodDescriptorShrinker. 55b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 56b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public MethodDescriptorShrinker() 57b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 58b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato this(null); 59b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 60b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 61b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 62b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 63b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Creates a new MethodDescriptorShrinker with an extra visitor. 64b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @param extraMemberVisitor an optional extra visitor for all methods whose 65b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * parameters have been simplified. 66b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 67b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public MethodDescriptorShrinker(MemberVisitor extraMemberVisitor) 68b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 69b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato this.extraMemberVisitor = extraMemberVisitor; 70b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 71b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 72b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 73b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Implementations for MemberVisitor. 74b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 75b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod) 76b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 77b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Update the descriptor if it has any unused parameters. 78b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato String descriptor = programMethod.getDescriptor(programClass); 79b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato String newDescriptor = shrinkDescriptor(programMethod, descriptor); 80b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 81b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (!descriptor.equals(newDescriptor)) 82b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 83b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Shrink the signature and parameter annotations. 84b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato programMethod.attributesAccept(programClass, this); 85b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 86b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato String name = programMethod.getName(programClass); 87b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato String newName = name; 88b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 89b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Append a code, if the method isn't a class instance initializer. 90b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (!name.equals(ClassConstants.INTERNAL_METHOD_NAME_INIT)) 91b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 92b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato newName += ClassConstants.SPECIAL_MEMBER_SEPARATOR + Long.toHexString(Math.abs((descriptor).hashCode())); 93b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 94b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 95b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (DEBUG) 96b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 97b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato System.out.println("MethodDescriptorShrinker:"); 98b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato System.out.println(" Class file = "+programClass.getName()); 99b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato System.out.println(" Method name = "+name); 100b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato System.out.println(" -> "+newName); 101b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato System.out.println(" Method descriptor = "+descriptor); 102b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato System.out.println(" -> "+newDescriptor); 103b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 104b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 105b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato ConstantPoolEditor constantPoolEditor = 106b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new ConstantPoolEditor(programClass); 107b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 108b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Update the name, if necessary. 109b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (!newName.equals(name)) 110b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 111b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato programMethod.u2nameIndex = 112b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato constantPoolEditor.addUtf8Constant(newName); 113b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 114b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 115b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Update the referenced classes. 116b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato programMethod.referencedClasses = 117b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato shrinkReferencedClasses(programMethod, 118b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato descriptor, 119b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato programMethod.referencedClasses); 120b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 121b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Finally, update the descriptor itself. 122b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato programMethod.u2descriptorIndex = 123b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato constantPoolEditor.addUtf8Constant(newDescriptor); 124b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 125b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Visit the method, if required. 126b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (extraMemberVisitor != null) 127b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 128b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato extraMemberVisitor.visitProgramMethod(programClass, programMethod); 129b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 130b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 131b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 132b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 133b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 134b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Implementations for AttributeVisitor. 135b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 136b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void visitAnyAttribute(Clazz clazz, Attribute attribute) {} 137b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 138b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 139b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void visitSignatureAttribute(Clazz clazz, Method method, SignatureAttribute signatureAttribute) 140b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 141b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Compute the new signature. 142b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato String signature = clazz.getString(signatureAttribute.u2signatureIndex); 143b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato String newSignature = shrinkDescriptor(method, signature); 144b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 145b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Update the signature. 146b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato signatureAttribute.u2signatureIndex = 147b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new ConstantPoolEditor((ProgramClass)clazz).addUtf8Constant(newSignature); 148b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 149b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Update the referenced classes. 150b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato signatureAttribute.referencedClasses = 151b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato shrinkReferencedClasses(method, 152b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato signature, 153b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato signatureAttribute.referencedClasses); 154b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 155b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 156b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 157b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void visitAnyParameterAnnotationsAttribute(Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute) 158b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 159b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int[] annotationsCounts = parameterAnnotationsAttribute.u2parameterAnnotationsCount; 160b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Annotation[][] annotations = parameterAnnotationsAttribute.parameterAnnotations; 161b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 162b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // All parameters of non-static methods are shifted by one in the local 163b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // variable frame. 164b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int parameterIndex = 165b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato (method.getAccessFlags() & ClassConstants.INTERNAL_ACC_STATIC) != 0 ? 166b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 0 : 1; 167b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 168b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int annotationIndex = 0; 169b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int newAnnotationIndex = 0; 170b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 171b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Go over the parameters. 172b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato String descriptor = method.getDescriptor(clazz); 173b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato InternalTypeEnumeration internalTypeEnumeration = 174b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new InternalTypeEnumeration(descriptor); 175b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 176b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato while (internalTypeEnumeration.hasMoreTypes()) 177b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 178b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato String type = internalTypeEnumeration.nextType(); 179b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (ParameterUsageMarker.isParameterUsed(method, parameterIndex)) 180b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 181b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato annotationsCounts[newAnnotationIndex] = annotationsCounts[annotationIndex]; 182b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato annotations[newAnnotationIndex++] = annotations[annotationIndex]; 183b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 184b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 185b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato annotationIndex++; 186b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 187b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato parameterIndex += ClassUtil.isInternalCategory2Type(type) ? 2 : 1; 188b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 189b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 190b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Update the number of parameters. 191b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato parameterAnnotationsAttribute.u2parametersCount = newAnnotationIndex; 192b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 193b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Clear the unused entries. 194b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato while (newAnnotationIndex < annotationIndex) 195b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 196b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato annotationsCounts[newAnnotationIndex] = 0; 197b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato annotations[newAnnotationIndex++] = null; 198b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 199b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 200b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 201b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 202b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Small utility methods. 203b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 204b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 205b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Returns a shrunk descriptor or signature of the given method. 206b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 207b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private String shrinkDescriptor(Method method, String descriptor) 208b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 209b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // All parameters of non-static methods are shifted by one in the local 210b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // variable frame. 211b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int parameterIndex = 212b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato (method.getAccessFlags() & ClassConstants.INTERNAL_ACC_STATIC) != 0 ? 213b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 0 : 1; 214b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 215b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Go over the parameters. 216b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato InternalTypeEnumeration internalTypeEnumeration = 217b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new InternalTypeEnumeration(descriptor); 218b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 219b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato StringBuffer newDescriptorBuffer = new StringBuffer(); 220b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 221b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato newDescriptorBuffer.append(internalTypeEnumeration.formalTypeParameters()); 222b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato newDescriptorBuffer.append(ClassConstants.INTERNAL_METHOD_ARGUMENTS_OPEN); 223b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 224b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato while (internalTypeEnumeration.hasMoreTypes()) 225b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 226b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato String type = internalTypeEnumeration.nextType(); 227b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (ParameterUsageMarker.isParameterUsed(method, parameterIndex)) 228b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 229b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato newDescriptorBuffer.append(type); 230b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 231b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato else if (DEBUG) 232b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 233b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato System.out.println(" Deleting parameter #"+parameterIndex+" ["+type+"]"); 234b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 235b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 236b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato parameterIndex += ClassUtil.isInternalCategory2Type(type) ? 2 : 1; 237b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 238b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 239b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato newDescriptorBuffer.append(ClassConstants.INTERNAL_METHOD_ARGUMENTS_CLOSE); 240b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato newDescriptorBuffer.append(internalTypeEnumeration.returnType()); 241b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 242b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato return newDescriptorBuffer.toString(); 243b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 244b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 245b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 246b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 247b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Shrinks the array of referenced classes of the given method. 248b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 249b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private Clazz[] shrinkReferencedClasses(Method method, 250b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato String descriptor, 251b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Clazz[] referencedClasses) 252b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 253b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (referencedClasses != null) 254b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 255b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // All parameters of non-static methods are shifted by one in the local 256b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // variable frame. 257b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int parameterIndex = 258b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato (method.getAccessFlags() & ClassConstants.INTERNAL_ACC_STATIC) != 0 ? 259b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 0 : 1; 260b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 261b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int referencedClassIndex = 0; 262b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int newReferencedClassIndex = 0; 263b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 264b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Go over the parameters. 265b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato InternalTypeEnumeration internalTypeEnumeration = 266b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new InternalTypeEnumeration(descriptor); 267b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 268b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Also look at the formal type parameters. 269b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato String type = internalTypeEnumeration.formalTypeParameters(); 270b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int count = new DescriptorClassEnumeration(type).classCount(); 271b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato for (int counter = 0; counter < count; counter++) 272b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 273b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato referencedClasses[newReferencedClassIndex++] = 274b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato referencedClasses[referencedClassIndex++]; 275b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 276b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 277b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato while (internalTypeEnumeration.hasMoreTypes()) 278b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 279b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Consider the classes referenced by this parameter type. 280b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato type = internalTypeEnumeration.nextType(); 281b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato count = new DescriptorClassEnumeration(type).classCount(); 282b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 283b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (ParameterUsageMarker.isParameterUsed(method, parameterIndex)) 284b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 285b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Copy the referenced classes. 286b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato for (int counter = 0; counter < count; counter++) 287b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 288b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato referencedClasses[newReferencedClassIndex++] = 289b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato referencedClasses[referencedClassIndex++]; 290b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 291b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 292b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato else 293b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 294b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Skip the referenced classes. 295b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato referencedClassIndex += count; 296b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 297b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 298b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato parameterIndex += ClassUtil.isInternalCategory2Type(type) ? 2 : 1; 299b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 300b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 301b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Also look at the return value. 302b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato type = internalTypeEnumeration.returnType(); 303b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato count = new DescriptorClassEnumeration(type).classCount(); 304b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato for (int counter = 0; counter < count; counter++) 305b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 306b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato referencedClasses[newReferencedClassIndex++] = 307b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato referencedClasses[referencedClassIndex++]; 308b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 309b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 310b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Clear the unused entries. 311b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato while (newReferencedClassIndex < referencedClassIndex) 312b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 313b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato referencedClasses[newReferencedClassIndex++] = null; 314b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 315b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 316b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 317b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato return referencedClasses; 318b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 319b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato} 320