KickJava   Java API By Example, From Geeks To Geeks.

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


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.attribute.*;
25 import proguard.classfile.constant.*;
26 import proguard.classfile.constant.visitor.ConstantVisitor;
27 import proguard.classfile.instruction.*;
28 import proguard.classfile.instruction.visitor.InstructionVisitor;
29 import proguard.classfile.util.*;
30 import proguard.classfile.visitor.*;
31
32 /**
33  * This class can tell whether an instruction has any side effects. Return
34  * instructions can be included or not.
35  *
36  * @see ReadWriteFieldMarker
37  * @see NoSideEffectMethodMarker
38  * @see SideEffectMethodMarker
39  * @author Eric Lafortune
40  */

41 public class SideEffectInstructionChecker
42 extends SimplifiedVisitor
43 implements InstructionVisitor,
44              ConstantVisitor,
45              MemberVisitor
46 {
47     private boolean includeReturnInstructions;
48
49     // A return value for the visitor methods.
50
private boolean hasSideEffects;
51
52
53     public SideEffectInstructionChecker(boolean includeReturnInstructions)
54     {
55         this.includeReturnInstructions = includeReturnInstructions;
56     }
57
58
59     public boolean hasSideEffects(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction)
60     {
61         hasSideEffects = false;
62
63         instruction.accept(clazz, method, codeAttribute, offset, this);
64
65         return hasSideEffects;
66     }
67
68
69     // Implementations for InstructionVisitor.
70

71     public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
72
73
74     public void visitSimpleInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction)
75     {
76         byte opcode = simpleInstruction.opcode;
77
78         // Check for instructions that might cause side effects.
79
if (opcode == InstructionConstants.OP_IASTORE ||
80             opcode == InstructionConstants.OP_LASTORE ||
81             opcode == InstructionConstants.OP_FASTORE ||
82             opcode == InstructionConstants.OP_DASTORE ||
83             opcode == InstructionConstants.OP_AASTORE ||
84             opcode == InstructionConstants.OP_BASTORE ||
85             opcode == InstructionConstants.OP_CASTORE ||
86             opcode == InstructionConstants.OP_SASTORE ||
87             opcode == InstructionConstants.OP_ATHROW ||
88             opcode == InstructionConstants.OP_MONITORENTER ||
89             opcode == InstructionConstants.OP_MONITOREXIT ||
90             (includeReturnInstructions &&
91              (opcode == InstructionConstants.OP_IRETURN ||
92               opcode == InstructionConstants.OP_LRETURN ||
93               opcode == InstructionConstants.OP_FRETURN ||
94               opcode == InstructionConstants.OP_DRETURN ||
95               opcode == InstructionConstants.OP_ARETURN ||
96               opcode == InstructionConstants.OP_RETURN)))
97         {
98             // These instructions always cause a side effect.
99
hasSideEffects = true;
100         }
101
102     }
103
104
105     public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction)
106     {
107         byte opcode = variableInstruction.opcode;
108
109         // Check for instructions that might cause side effects.
110
if (includeReturnInstructions &&
111             opcode == InstructionConstants.OP_RET)
112         {
113             hasSideEffects = true;
114         }
115     }
116
117
118     public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
119     {
120         byte opcode = constantInstruction.opcode;
121
122         // Check for instructions that might cause side effects.
123
if (opcode == InstructionConstants.OP_PUTSTATIC ||
124             opcode == InstructionConstants.OP_PUTFIELD ||
125             opcode == InstructionConstants.OP_INVOKEVIRTUAL ||
126             opcode == InstructionConstants.OP_INVOKESPECIAL ||
127             opcode == InstructionConstants.OP_INVOKESTATIC ||
128             opcode == InstructionConstants.OP_INVOKEINTERFACE)
129         {
130             // Check if the field is write-only or volatile, or if the invoked
131
// method is causing any side effects.
132
clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
133         }
134     }
135
136
137     public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction)
138     {
139         byte opcode = branchInstruction.opcode;
140
141         // Check for instructions that might cause side effects.
142
if (includeReturnInstructions &&
143             (opcode == InstructionConstants.OP_JSR ||
144              opcode == InstructionConstants.OP_JSR_W))
145         {
146             hasSideEffects = true;
147         }
148     }
149
150
151     // Implementations for ConstantVisitor.
152

153     public void visitFieldrefConstant(Clazz clazz, FieldrefConstant fieldrefConstant)
154     {
155         // We'll have to assume accessing an unknown field has side effects.
156
hasSideEffects = true;
157
158         // Check the referenced field.
159
fieldrefConstant.referencedMemberAccept(this);
160     }
161
162
163     public void visitAnyMethodrefConstant(Clazz clazz, RefConstant refConstant)
164     {
165         Member referencedMember = refConstant.referencedMember;
166
167         // Do we have a reference to the method?
168
if (referencedMember == null)
169         {
170             // We'll have to assume invoking the unknown method has side effects.
171
hasSideEffects = true;
172         }
173         else
174         {
175             // First check the referenced method itself.
176
refConstant.referencedMemberAccept(this);
177
178             // If the result isn't conclusive, check down the hierarchy.
179
if (!hasSideEffects)
180             {
181                 Clazz referencedClass = refConstant.referencedClass;
182                 Method referencedMethod = (Method)referencedMember;
183
184                 // Check all other implementations of the method in the class
185
// hierarchy.
186
referencedClass.methodImplementationsAccept(referencedMethod,
187                                                             false,
188                                                             this);
189             }
190         }
191     }
192
193
194     // Implementations for MemberVisitor.
195

196     public void visitProgramField(ProgramClass programClass, ProgramField programField)
197     {
198         hasSideEffects = ReadWriteFieldMarker.isRead(programField);
199     }
200
201
202     public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
203     {
204         hasSideEffects = hasSideEffects ||
205                          SideEffectMethodMarker.hasSideEffects(programMethod);
206     }
207
208
209     public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField)
210     {
211         hasSideEffects = true;
212     }
213
214
215     public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
216     {
217         hasSideEffects = hasSideEffects ||
218                          !NoSideEffectMethodMarker.hasNoSideEffects(libraryMethod);
219     }
220 }
221
Popular Tags