• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  */
21 package proguard.optimize.info;
22 
23 import proguard.classfile.*;
24 import proguard.classfile.util.*;
25 import proguard.evaluation.value.Value;
26 
27 /**
28  * This class stores some optimization information that can be attached to
29  * a method.
30  *
31  * @author Eric Lafortune
32  */
33 public class MethodOptimizationInfo
34 {
35     private boolean hasNoSideEffects      = false;
36     private boolean hasSideEffects        = false;
37     private boolean canBeMadePrivate      = true;
38     private boolean catchesExceptions     = false;
39     private boolean branchesBackward      = false;
40     private boolean invokesSuperMethods   = false;
41     private boolean accessesPrivateCode   = false;
42     private boolean accessesPackageCode   = false;
43     private boolean accessesProtectedCode = false;
44     private int     invocationCount       = 0;
45     private int     parameterSize         = 0;
46     private long    usedParameters        = 0L;
47     private Value[] parameters;
48     private Value   returnValue;
49 
50 
51     /**
52      * Creates a new MethodOptimizationInfo for the given method.
53      */
MethodOptimizationInfo(Clazz clazz, Method method)54     public MethodOptimizationInfo(Clazz clazz, Method method)
55     {
56         // Set up an array of the right size for storing information about the
57         // passed parameters.
58         int parameterCount =
59             ClassUtil.internalMethodParameterCount(method.getDescriptor(clazz));
60 
61         if ((method.getAccessFlags() & ClassConstants.INTERNAL_ACC_STATIC) == 0)
62         {
63             parameterCount++;
64         }
65 
66         if (parameterCount > 0)
67         {
68             parameters = new Value[parameterCount];
69         }
70     }
71 
72 
setNoSideEffects()73     public void setNoSideEffects()
74     {
75         hasNoSideEffects = true;
76     }
77 
78 
hasNoSideEffects()79     public boolean hasNoSideEffects()
80     {
81         return hasNoSideEffects;
82     }
83 
84 
setSideEffects()85     public void setSideEffects()
86     {
87         hasSideEffects = true;
88     }
89 
90 
hasSideEffects()91     public boolean hasSideEffects()
92     {
93         return hasSideEffects;
94     }
95 
96 
setCanNotBeMadePrivate()97     public void setCanNotBeMadePrivate()
98     {
99         canBeMadePrivate = false;
100     }
101 
102 
canBeMadePrivate()103     public boolean canBeMadePrivate()
104     {
105         return canBeMadePrivate;
106     }
107 
108 
setCatchesExceptions()109     public void setCatchesExceptions()
110     {
111         catchesExceptions = true;
112     }
113 
114 
catchesExceptions()115     public boolean catchesExceptions()
116     {
117         return catchesExceptions;
118     }
119 
120 
setBranchesBackward()121     public void setBranchesBackward()
122     {
123         branchesBackward = true;
124     }
125 
126 
branchesBackward()127     public boolean branchesBackward()
128     {
129         return branchesBackward;
130     }
131 
132 
setInvokesSuperMethods()133     public void setInvokesSuperMethods()
134     {
135         invokesSuperMethods = true;
136     }
137 
138 
invokesSuperMethods()139     public boolean invokesSuperMethods()
140     {
141         return invokesSuperMethods;
142     }
143 
144 
setAccessesPrivateCode()145     public void setAccessesPrivateCode()
146     {
147         accessesPrivateCode = true;
148     }
149 
150 
accessesPrivateCode()151     public boolean accessesPrivateCode()
152     {
153         return accessesPrivateCode;
154     }
155 
156 
setAccessesPackageCode()157     public void setAccessesPackageCode()
158     {
159         accessesPackageCode = true;
160     }
161 
162 
accessesPackageCode()163     public boolean accessesPackageCode()
164     {
165         return accessesPackageCode;
166     }
167 
168 
setAccessesProtectedCode()169     public void setAccessesProtectedCode()
170     {
171         accessesProtectedCode = true;
172     }
173 
174 
accessesProtectedCode()175     public boolean accessesProtectedCode()
176     {
177         return accessesProtectedCode;
178     }
179 
180 
incrementInvocationCount()181     public void incrementInvocationCount()
182     {
183         invocationCount++;
184     }
185 
186 
getInvocationCount()187     public int getInvocationCount()
188     {
189         return invocationCount;
190     }
191 
192 
setParameterSize(int parameterSize)193     public void setParameterSize(int parameterSize)
194     {
195         this.parameterSize = parameterSize;
196     }
197 
198 
getParameterSize()199     public int getParameterSize()
200     {
201         return parameterSize;
202     }
203 
204 
setParameterUsed(int parameterIndex)205     public void setParameterUsed(int parameterIndex)
206     {
207         usedParameters |= 1 << parameterIndex;
208     }
209 
210 
setUsedParameters(long usedParameters)211     public void setUsedParameters(long usedParameters)
212     {
213         this.usedParameters = usedParameters;
214     }
215 
216 
isParameterUsed(int parameterIndex)217     public boolean isParameterUsed(int parameterIndex)
218     {
219         return parameterIndex >= 64 || (usedParameters & (1 << parameterIndex)) != 0;
220     }
221 
222 
getUsedParameters()223     public long getUsedParameters()
224     {
225         return usedParameters;
226     }
227 
228 
generalizeParameter(int parameterIndex, Value parameter)229     public void generalizeParameter(int parameterIndex, Value parameter)
230     {
231         parameters[parameterIndex] = parameters[parameterIndex] != null ?
232             parameters[parameterIndex].generalize(parameter) :
233             parameter;
234     }
235 
236 
getParameter(int parameterIndex)237     public Value getParameter(int parameterIndex)
238     {
239         return parameters != null ?
240             parameters[parameterIndex] :
241             null;
242     }
243 
244 
generalizeReturnValue(Value returnValue)245     public void generalizeReturnValue(Value returnValue)
246     {
247         this.returnValue = this.returnValue != null ?
248             this.returnValue.generalize(returnValue) :
249             returnValue;
250     }
251 
252 
getReturnValue()253     public Value getReturnValue()
254     {
255         return returnValue;
256     }
257 
258 
merge(MethodOptimizationInfo other)259     public void merge(MethodOptimizationInfo other)
260     {
261         if (other != null)
262         {
263             this.hasNoSideEffects      &= other.hasNoSideEffects;
264             this.hasSideEffects        |= other.hasSideEffects;
265             //this.canBeMadePrivate    &= other.canBeMadePrivate;
266             this.catchesExceptions     |= other.catchesExceptions;
267             this.branchesBackward      |= other.branchesBackward;
268             this.invokesSuperMethods   |= other.invokesSuperMethods;
269             this.accessesPrivateCode   |= other.accessesPrivateCode;
270             this.accessesPackageCode   |= other.accessesPackageCode;
271             this.accessesProtectedCode |= other.accessesProtectedCode;
272         }
273         else
274         {
275             this.hasNoSideEffects      = false;
276             this.hasSideEffects        = true;
277             //this.canBeMadePrivate    = false;
278             this.catchesExceptions     = true;
279             this.branchesBackward      = true;
280             this.invokesSuperMethods   = true;
281             this.accessesPrivateCode   = true;
282             this.accessesPackageCode   = true;
283             this.accessesProtectedCode = true;
284         }
285     }
286 
287 
setMethodOptimizationInfo(Clazz clazz, Method method)288     public static void setMethodOptimizationInfo(Clazz clazz, Method method)
289     {
290         MethodLinker.lastMember(method).setVisitorInfo(new MethodOptimizationInfo(clazz, method));
291     }
292 
293 
getMethodOptimizationInfo(Method method)294     public static MethodOptimizationInfo getMethodOptimizationInfo(Method method)
295     {
296         Object visitorInfo = MethodLinker.lastMember(method).getVisitorInfo();
297 
298         return visitorInfo instanceof MethodOptimizationInfo ?
299             (MethodOptimizationInfo)visitorInfo :
300             null;
301     }
302 }
303