Home | History | Annotate | Download | only in optimize
      1 /*
      2  * ProGuard -- shrinking, optimization, obfuscation, and preverification
      3  *             of Java bytecode.
      4  *
      5  * Copyright (c) 2002-2014 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;
     22 
     23 import proguard.classfile.*;
     24 import proguard.classfile.editor.ClassReferenceFixer;
     25 import proguard.classfile.util.*;
     26 import proguard.classfile.visitor.MemberVisitor;
     27 import proguard.evaluation.value.Value;
     28 import proguard.optimize.evaluation.StoringInvocationUnit;
     29 
     30 /**
     31  * This MemberVisitor specializes parameters in the descriptors of the
     32  * methods that it visits.
     33  *
     34  * @see StoringInvocationUnit
     35  * @see ClassReferenceFixer
     36  * @author Eric Lafortune
     37  */
     38 public class MemberDescriptorSpecializer
     39 extends      SimplifiedVisitor
     40 implements   MemberVisitor
     41 {
     42     private static final boolean DEBUG = false;
     43 
     44 
     45     private final MemberVisitor extraParameterMemberVisitor;
     46 
     47 
     48     /**
     49      * Creates a new MethodDescriptorShrinker.
     50      */
     51     public MemberDescriptorSpecializer()
     52     {
     53         this(null);
     54     }
     55 
     56 
     57     /**
     58      * Creates a new MethodDescriptorShrinker with an extra visitor.
     59      * @param extraParameterMemberVisitor an optional extra visitor for all
     60      *                                    class members whose parameters have
     61      *                                    been specialized.
     62      */
     63     public MemberDescriptorSpecializer(MemberVisitor extraParameterMemberVisitor)
     64     {
     65         this.extraParameterMemberVisitor = extraParameterMemberVisitor;
     66     }
     67 
     68 
     69     // Implementations for MemberVisitor.
     70 
     71     public void visitProgramField(ProgramClass programClass, ProgramField programField)
     72     {
     73         Value parameterValue = StoringInvocationUnit.getFieldValue(programField);
     74         if (parameterValue.computationalType() == Value.TYPE_REFERENCE)
     75         {
     76             Clazz referencedClass = parameterValue.referenceValue().getReferencedClass();
     77             if (programField.referencedClass != referencedClass)
     78             {
     79                 if (DEBUG)
     80                 {
     81                     System.out.println("MemberDescriptorSpecializer: "+programClass.getName()+"."+programField.getName(programClass)+" "+programField.getDescriptor(programClass));
     82                     System.out.println("  "+programField.referencedClass.getName()+" -> "+referencedClass.getName());
     83                 }
     84 
     85                 programField.referencedClass = referencedClass;
     86 
     87                 // Visit the field, if required.
     88                 if (extraParameterMemberVisitor != null)
     89                 {
     90                     extraParameterMemberVisitor.visitProgramField(programClass, programField);
     91                 }
     92             }
     93         }
     94     }
     95 
     96 
     97     public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
     98     {
     99         // All parameters of non-static methods are shifted by one in the local
    100         // variable frame.
    101         int firstParameterIndex =
    102             (programMethod.getAccessFlags() & ClassConstants.ACC_STATIC) != 0 ?
    103                 0 : 1;
    104 
    105         int parameterCount =
    106             ClassUtil.internalMethodParameterCount(programMethod.getDescriptor(programClass));
    107 
    108         int classIndex = 0;
    109 
    110         // Go over the parameters.
    111         for (int parameterIndex = firstParameterIndex; parameterIndex < parameterCount; parameterIndex++)
    112         {
    113             Value parameterValue = StoringInvocationUnit.getMethodParameterValue(programMethod, parameterIndex);
    114              if (parameterValue.computationalType() == Value.TYPE_REFERENCE)
    115              {
    116                  Clazz referencedClass = parameterValue.referenceValue().getReferencedClass();
    117                  if (programMethod.referencedClasses[classIndex] != referencedClass)
    118                  {
    119                      if (DEBUG)
    120                      {
    121                          System.out.println("MemberDescriptorSpecializer: "+programClass.getName()+"."+programMethod.getName(programClass)+programMethod.getDescriptor(programClass));
    122                          System.out.println("  "+programMethod.referencedClasses[classIndex].getName()+" -> "+referencedClass.getName());
    123                      }
    124 
    125                      programMethod.referencedClasses[classIndex] = referencedClass;
    126 
    127                      // Visit the method, if required.
    128                      if (extraParameterMemberVisitor != null)
    129                      {
    130                          extraParameterMemberVisitor.visitProgramMethod(programClass, programMethod);
    131                      }
    132                  }
    133 
    134                  classIndex++;
    135              }
    136         }
    137     }
    138 }
    139