Home | History | Annotate | Download | only in info
      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