KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > proguard > optimize > info > SideEffectMethodMarker


1 /*
2  * ProGuard -- shrinking, optimization, obfuscation, and preverification
3  * of Java bytecode.
4  *
5  * Copyright (c) 2002-2007 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.SimplifiedVisitor;
25 import proguard.classfile.attribute.*;
26 import proguard.classfile.attribute.visitor.AttributeVisitor;
27 import proguard.classfile.instruction.*;
28 import proguard.classfile.visitor.*;
29
30 /**
31  * This ClassPoolVisitor marks all methods that have side effects.
32  *
33  * @see ReadWriteFieldMarker
34  * @see NoSideEffectMethodMarker
35  * @author Eric Lafortune
36  */

37 public class SideEffectMethodMarker
38 extends SimplifiedVisitor
39 implements ClassPoolVisitor,
40              ClassVisitor,
41              MemberVisitor,
42              AttributeVisitor
43 {
44     // A reusable object for checking whether instructions have side effects.
45
private SideEffectInstructionChecker sideEffectInstructionChecker = new SideEffectInstructionChecker(false);
46
47     // Parameters and values for visitor methods.
48
private int newSideEffectCount;
49     private boolean hasSideEffects;
50
51
52     // Implementations for ClassPoolVisitor.
53

54     public void visitClassPool(ClassPool classPool)
55     {
56         // Go over all classes and their methods, marking if they have side
57
// effects, until no new cases can be found.
58
do
59         {
60             newSideEffectCount = 0;
61
62             // Go over all classes and their methods once.
63
classPool.classesAccept(this);
64         }
65         while (newSideEffectCount > 0);
66     }
67
68
69     // Implementations for ClassVisitor.
70

71     public void visitProgramClass(ProgramClass programClass)
72     {
73         // Go over all methods.
74
programClass.methodsAccept(this);
75     }
76
77
78     // Implementations for MemberVisitor.
79

80     public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
81     {
82         if (!hasSideEffects(programMethod) &&
83             !NoSideEffectMethodMarker.hasNoSideEffects(programMethod))
84         {
85             // Set the return value, in case the method doesn't have a code
86
// attribute (a native method or an abstract method).
87
hasSideEffects = (programMethod.getAccessFlags() & ClassConstants.INTERNAL_ACC_NATIVE) != 0;
88
89             programMethod.attributesAccept(programClass, this);
90
91             // Mark the method depending on the return value.
92
if (hasSideEffects)
93             {
94                 markSideEffects(programMethod);
95
96                 newSideEffectCount++;
97             }
98         }
99     }
100
101
102     // Implementations for AttributeVisitor.
103

104     public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
105
106
107     public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
108     {
109         // Remember whether the code has any side effects.
110
hasSideEffects = hasSideEffects(clazz, method, codeAttribute);
111     }
112
113
114     // Small utility methods.
115

116     /**
117      * Returns whether the given code has any side effects.
118      */

119     private boolean hasSideEffects(Clazz clazz,
120                                    Method method,
121                                    CodeAttribute codeAttribute)
122     {
123         byte[] code = codeAttribute.code;
124         int length = codeAttribute.u4codeLength;
125
126         // Go over all instructions.
127
int offset = 0;
128         do
129         {
130             // Get the current instruction.
131
Instruction instruction = InstructionFactory.create(code, offset);
132
133             // Check if it may be throwing exceptions.
134
if (sideEffectInstructionChecker.hasSideEffects(clazz,
135                                                             method,
136                                                             codeAttribute,
137                                                             offset,
138                                                             instruction))
139             {
140                 return true;
141             }
142
143             // Go to the next instruction.
144
offset += instruction.length(offset);
145         }
146         while (offset < length);
147
148         return false;
149     }
150
151
152     private static void markSideEffects(Method method)
153     {
154         MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
155         if (info != null)
156         {
157             info.setSideEffects();
158         }
159     }
160
161
162     public static boolean hasSideEffects(Method method)
163     {
164         MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
165         return info == null ||
166                info.hasSideEffects();
167     }
168 }
169
Popular Tags