MethodOptimizationInfo.java revision b9cc48a43ed984587c939d02fba5316bf5c0df6e
1/*
2 * ProGuard -- shrinking, optimization, obfuscation, and preverification
3 *             of Java bytecode.
4 *
5 * Copyright (c) 2002-2013 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.info;
22
23import proguard.classfile.*;
24import proguard.classfile.util.*;
25import 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 */
33public 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     */
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
73    public void setNoSideEffects()
74    {
75        hasNoSideEffects = true;
76    }
77
78
79    public boolean hasNoSideEffects()
80    {
81        return hasNoSideEffects;
82    }
83
84
85    public void setSideEffects()
86    {
87        hasSideEffects = true;
88    }
89
90
91    public boolean hasSideEffects()
92    {
93        return hasSideEffects;
94    }
95
96
97    public void setCanNotBeMadePrivate()
98    {
99        canBeMadePrivate = false;
100    }
101
102
103    public boolean canBeMadePrivate()
104    {
105        return canBeMadePrivate;
106    }
107
108
109    public void setCatchesExceptions()
110    {
111        catchesExceptions = true;
112    }
113
114
115    public boolean catchesExceptions()
116    {
117        return catchesExceptions;
118    }
119
120
121    public void setBranchesBackward()
122    {
123        branchesBackward = true;
124    }
125
126
127    public boolean branchesBackward()
128    {
129        return branchesBackward;
130    }
131
132
133    public void setInvokesSuperMethods()
134    {
135        invokesSuperMethods = true;
136    }
137
138
139    public boolean invokesSuperMethods()
140    {
141        return invokesSuperMethods;
142    }
143
144
145    public void setAccessesPrivateCode()
146    {
147        accessesPrivateCode = true;
148    }
149
150
151    public boolean accessesPrivateCode()
152    {
153        return accessesPrivateCode;
154    }
155
156
157    public void setAccessesPackageCode()
158    {
159        accessesPackageCode = true;
160    }
161
162
163    public boolean accessesPackageCode()
164    {
165        return accessesPackageCode;
166    }
167
168
169    public void setAccessesProtectedCode()
170    {
171        accessesProtectedCode = true;
172    }
173
174
175    public boolean accessesProtectedCode()
176    {
177        return accessesProtectedCode;
178    }
179
180
181    public void incrementInvocationCount()
182    {
183        invocationCount++;
184    }
185
186
187    public int getInvocationCount()
188    {
189        return invocationCount;
190    }
191
192
193    public void setParameterSize(int parameterSize)
194    {
195        this.parameterSize = parameterSize;
196    }
197
198
199    public int getParameterSize()
200    {
201        return parameterSize;
202    }
203
204
205    public void setParameterUsed(int parameterIndex)
206    {
207        usedParameters |= 1L << parameterIndex;
208    }
209
210
211    public void setUsedParameters(long usedParameters)
212    {
213        this.usedParameters = usedParameters;
214    }
215
216
217    public boolean isParameterUsed(int parameterIndex)
218    {
219        return parameterIndex >= 64 || (usedParameters & (1L << parameterIndex)) != 0;
220    }
221
222
223    public long getUsedParameters()
224    {
225        return usedParameters;
226    }
227
228
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
237    public Value getParameter(int parameterIndex)
238    {
239        return parameters != null ?
240            parameters[parameterIndex] :
241            null;
242    }
243
244
245    public void generalizeReturnValue(Value returnValue)
246    {
247        this.returnValue = this.returnValue != null ?
248            this.returnValue.generalize(returnValue) :
249            returnValue;
250    }
251
252
253    public Value getReturnValue()
254    {
255        return returnValue;
256    }
257
258
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
288    public static void setMethodOptimizationInfo(Clazz clazz, Method method)
289    {
290        MethodLinker.lastMember(method).setVisitorInfo(new MethodOptimizationInfo(clazz, method));
291    }
292
293
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