1 /* 2 * ProGuard -- shrinking, optimization, obfuscation, and preverification 3 * of Java bytecode. 4 * 5 * Copyright (c) 2002-2009 Eric Lafortune (eric (at) 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 */ 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 |= 1 << 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 & (1 << 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