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