1/* 2 * ProGuard -- shrinking, optimization, obfuscation, and preverification 3 * of Java bytecode. 4 * 5 * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu) 6 * 7 * This program is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License as published by the Free 9 * Software Foundation; either version 2 of the License, or (at your option) 10 * any later version. 11 * 12 * This program is distributed in the hope that it will be useful, but WITHOUT 13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 15 * more details. 16 * 17 * You should have received a copy of the GNU General Public License along 18 * with this program; if not, write to the Free Software Foundation, Inc., 19 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 */ 21package proguard.optimize; 22 23import proguard.classfile.*; 24import proguard.classfile.editor.ClassReferenceFixer; 25import proguard.classfile.util.*; 26import proguard.classfile.visitor.MemberVisitor; 27import proguard.evaluation.value.Value; 28import proguard.optimize.evaluation.StoringInvocationUnit; 29 30/** 31 * This MemberVisitor specializes parameters in the descriptors of the 32 * methods that it visits. 33 * 34 * @see StoringInvocationUnit 35 * @see ClassReferenceFixer 36 * @author Eric Lafortune 37 */ 38public class MemberDescriptorSpecializer 39extends SimplifiedVisitor 40implements MemberVisitor 41{ 42 private static final boolean DEBUG = true; 43 44 45 private final MemberVisitor extraParameterMemberVisitor; 46 47 48 /** 49 * Creates a new MethodDescriptorShrinker. 50 */ 51 public MemberDescriptorSpecializer() 52 { 53 this(null); 54 } 55 56 57 /** 58 * Creates a new MethodDescriptorShrinker with an extra visitor. 59 * @param extraParameterMemberVisitor an optional extra visitor for all 60 * class members whose parameters have 61 * been specialized. 62 */ 63 public MemberDescriptorSpecializer(MemberVisitor extraParameterMemberVisitor) 64 { 65 this.extraParameterMemberVisitor = extraParameterMemberVisitor; 66 } 67 68 69 // Implementations for MemberVisitor. 70 71 public void visitProgramField(ProgramClass programClass, ProgramField programField) 72 { 73 Value parameterValue = StoringInvocationUnit.getFieldValue(programField); 74 if (parameterValue.computationalType() == Value.TYPE_REFERENCE) 75 { 76 Clazz referencedClass = parameterValue.referenceValue().getReferencedClass(); 77 if (programField.referencedClass != referencedClass) 78 { 79 if (DEBUG) 80 { 81 System.out.println("MemberDescriptorSpecializer: "+programClass.getName()+"."+programField.getName(programClass)+" "+programField.getDescriptor(programClass)); 82 System.out.println(" "+programField.referencedClass.getName()+" -> "+referencedClass.getName()); 83 } 84 85 programField.referencedClass = referencedClass; 86 87 // Visit the field, if required. 88 if (extraParameterMemberVisitor != null) 89 { 90 extraParameterMemberVisitor.visitProgramField(programClass, programField); 91 } 92 } 93 } 94 } 95 96 97 public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod) 98 { 99 // All parameters of non-static methods are shifted by one in the local 100 // variable frame. 101 int firstParameterIndex = 102 (programMethod.getAccessFlags() & ClassConstants.INTERNAL_ACC_STATIC) != 0 ? 103 0 : 1; 104 105 int parameterCount = 106 ClassUtil.internalMethodParameterCount(programMethod.getDescriptor(programClass)); 107 108 int classIndex = 0; 109 110 // Go over the parameters. 111 for (int parameterIndex = firstParameterIndex; parameterIndex < parameterCount; parameterIndex++) 112 { 113 Value parameterValue = StoringInvocationUnit.getMethodParameterValue(programMethod, parameterIndex); 114 if (parameterValue.computationalType() == Value.TYPE_REFERENCE) 115 { 116 Clazz referencedClass = parameterValue.referenceValue().getReferencedClass(); 117 if (programMethod.referencedClasses[classIndex] != referencedClass) 118 { 119 if (DEBUG) 120 { 121 System.out.println("MemberDescriptorSpecializer: "+programClass.getName()+"."+programMethod.getName(programClass)+programMethod.getDescriptor(programClass)); 122 System.out.println(" "+programMethod.referencedClasses[classIndex].getName()+" -> "+referencedClass.getName()); 123 } 124 125 programMethod.referencedClasses[classIndex] = referencedClass; 126 127 // Visit the method, if required. 128 if (extraParameterMemberVisitor != null) 129 { 130 extraParameterMemberVisitor.visitProgramMethod(programClass, programMethod); 131 } 132 } 133 134 classIndex++; 135 } 136 } 137 } 138} 139