KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > proguard > optimize > info > ParameterUsageMarker


1 /*
2  * ProGuard -- shrinking, optimization, obfuscation, and preverification
3  * of Java bytecode.
4  *
5  * Copyright (c) 2002-2007 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  */

21 package proguard.optimize.info;
22
23 import proguard.classfile.*;
24 import proguard.classfile.util.*;
25 import proguard.classfile.visitor.MemberVisitor;
26 import proguard.optimize.MethodDescriptorShrinker;
27
28 /**
29  * This MemberVisitor counts the parameters and marks the used parameters
30  * of the methods that it visits. It also marks the 'this' parameters of
31  * methods that have a hierarchy.
32  *
33  * @author Eric Lafortune
34  */

35 public class ParameterUsageMarker
36 extends SimplifiedVisitor
37 implements MemberVisitor
38 {
39     private static final boolean DEBUG = false;
40
41
42     private VariableUsageMarker variableUsageMarker = new VariableUsageMarker();
43
44
45     // Implementations for MemberVisitor.
46

47     public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
48     {
49         int parameterSize = parameterSize(programClass, programMethod);
50         if (parameterSize > 0)
51         {
52             // Is it a native method?
53
int accessFlags = programMethod.getAccessFlags();
54             if ((accessFlags & ClassConstants.INTERNAL_ACC_ABSTRACT) == 0)
55             {
56                 // Mark all parameters.
57
markUsedParameters(programMethod, -1L);
58             }
59
60             // Is it an abstract method?
61
else if ((accessFlags & ClassConstants.INTERNAL_ACC_ABSTRACT) != 0)
62             {
63                 // Mark the 'this' parameter.
64
markParameterUsed(programMethod, 0);
65             }
66
67             // Is it a non-native, concrete method?
68
else
69             {
70                 // Figure out the local variables that are used by the code.
71
programMethod.attributesAccept(programClass, variableUsageMarker);
72
73                 // Mark the parameters that are used by the code.
74
for (int index = 0; index < parameterSize; index++)
75                 {
76                     if (variableUsageMarker.isVariableUsed(index))
77                     {
78                         markParameterUsed(programMethod, index);
79                     }
80                 }
81
82                 // Can the method have other implementations, or is it a class
83
// instance initializer?
84
if (programClass.mayHaveImplementations(programMethod) ||
85                     programMethod.getName(programClass).equals(ClassConstants.INTERNAL_METHOD_NAME_INIT))
86                 {
87                     // Mark the 'this' parameter.
88
markParameterUsed(programMethod, 0);
89                 }
90             }
91
92             if (DEBUG)
93             {
94                 System.out.print("ParameterUsageMarker: ["+programClass.getName() +"."+programMethod.getName(programClass)+programMethod.getDescriptor(programClass)+"]: ");
95                 for (int index = 0; index < parameterSize; index++)
96                 {
97                     System.out.print(isParameterUsed(programMethod, index) ? '+' : '-');
98                 }
99                 System.out.println();
100             }
101
102         }
103
104         // Set the parameter size.
105
setParameterSize(programMethod, parameterSize);
106     }
107
108
109     public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
110     {
111         // Can the method have other implementations?
112
if (libraryClass.mayHaveImplementations(libraryMethod))
113         {
114             // All implementations must keep all parameters of this method,
115
// including the 'this' parameter.
116
long usedParameters = -1L;
117
118             // Mark it.
119
markUsedParameters(libraryMethod, usedParameters);
120         }
121     }
122
123
124     // Small utility methods.
125

126     /**
127      * Sets the total size of the parameters.
128      */

129     private static void setParameterSize(Method method, int parameterSize)
130     {
131         MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
132         if (info != null)
133         {
134             info.setParameterSize(parameterSize);
135         }
136     }
137
138
139     /**
140      * Returns the total size of the parameters.
141      */

142     public static int getParameterSize(Method method)
143     {
144         MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
145         return info != null ? info.getParameterSize() : 0;
146     }
147
148
149     /**
150      * Marks the given parameter as being used.
151      */

152     public static void markParameterUsed(Method method, int variableIndex)
153     {
154         MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
155         if (info != null)
156         {
157             info.setParameterUsed(variableIndex);
158         }
159     }
160
161
162     /**
163      * Marks the given parameters as being used.
164      */

165     public static void markUsedParameters(Method method, long usedParameters)
166     {
167         MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
168         if (info != null)
169         {
170             info.setUsedParameters(info.getUsedParameters() | usedParameters);
171         }
172     }
173
174
175     /**
176      * Returns whether the given parameter is being used.
177      */

178     public static boolean isParameterUsed(Method method, int variableIndex)
179     {
180         MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
181         return info == null ||
182                info.isParameterUsed(variableIndex);
183     }
184
185
186     /**
187      * Returns which parameters are being used.
188      */

189     public static long getUsedParameters(Method method)
190     {
191         MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
192         return info != null ? info.getUsedParameters() : -1L;
193     }
194
195
196     /**
197      * Returns a bit mask of 1-bits of the given size.
198      */

199     private int parameterMask(int parameterSize)
200     {
201         return (1 << parameterSize) - 1;
202     }
203
204
205     /**
206      * Returns the parameter size of the given method, including the 'this'
207      * parameter, if any.
208      */

209     private int parameterSize(Clazz clazz, Method method)
210     {
211         int parameterSize = ClassUtil.internalMethodParameterSize(method.getDescriptor(clazz));
212         if ((method.getAccessFlags() & ClassConstants.INTERNAL_ACC_STATIC) == 0)
213         {
214             parameterSize++;
215         }
216
217         return parameterSize;
218     }
219 }
220
Popular Tags