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