KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > proguard > evaluation > BasicInvocationUnit


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 library 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 library 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 Lesser General Public License
15  * for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with this library; if not, write to the Free Software Foundation,
19  * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20  */

21 package proguard.evaluation;
22
23 import proguard.classfile.util.*;
24 import proguard.classfile.constant.visitor.ConstantVisitor;
25 import proguard.classfile.constant.*;
26 import proguard.classfile.visitor.MemberVisitor;
27 import proguard.classfile.*;
28 import proguard.classfile.instruction.*;
29 import proguard.classfile.attribute.CodeAttribute;
30 import proguard.evaluation.value.*;
31
32 /**
33  * This InvocationUnit sets up the variables for entering a method,
34  * and it updates the stack for the invocation of a class member,
35  * using simple values.
36  *
37  * @author Eric Lafortune
38  */

39 public class BasicInvocationUnit
40 extends SimplifiedVisitor
41 implements InvocationUnit,
42              ConstantVisitor,
43              MemberVisitor
44 {
45     private ValueFactory valueFactory = new ValueFactory();
46
47     // Fields acting as parameters between the visitor methods.
48
private boolean isStatic;
49     private boolean isLoad;
50     private Stack stack;
51     private Clazz returnTypeClass;
52
53
54     /**
55      * Sets up the given variables for entering the given method.
56      */

57     public void enterMethod(Clazz clazz, Method method, Variables variables)
58     {
59         String JavaDoc descriptor = method.getDescriptor(clazz);
60
61         // Initialize the parameters.
62
boolean isStatic =
63             (method.getAccessFlags() & ClassConstants.INTERNAL_ACC_STATIC) != 0;
64
65         // Count the number of parameters, taking into account their categories.
66
int parameterSize = ClassUtil.internalMethodParameterSize(descriptor);
67         if (!isStatic)
68         {
69             parameterSize++;
70         }
71
72         // Reuse the existing parameters object, ensuring the right size.
73
variables.reset(parameterSize);
74
75         // Go over the parameters again.
76
InternalTypeEnumeration internalTypeEnumeration =
77             new InternalTypeEnumeration(descriptor);
78
79         int parameterIndex = 0;
80         int variableIndex = 0;
81
82         // Put the 'this' reference in variable 0.
83
if (!isStatic)
84         {
85             // Get the reference value.
86
Value value = getMethodParameterValue(clazz,
87                                                   method,
88                                                   parameterIndex++,
89                                                   ClassUtil.internalTypeFromClassName(clazz.getName()),
90                                                   clazz);
91
92             // Store the value in variable 0.
93
variables.store(variableIndex++, value);
94         }
95
96         Clazz[] referencedClasses = ((ProgramMethod)method).referencedClasses;
97         int referencedClassIndex = 0;
98
99         // Set up the variables corresponding to the parameter types and values.
100
while (internalTypeEnumeration.hasMoreTypes())
101         {
102             String JavaDoc type = internalTypeEnumeration.nextType();
103
104             Clazz referencedClass = referencedClasses != null &&
105                                     ClassUtil.isInternalClassType(type) ?
106                 referencedClasses[referencedClassIndex++] :
107                 null;
108
109             // Get the parameter value.
110
Value value = getMethodParameterValue(clazz,
111                                                   method,
112                                                   parameterIndex++,
113                                                   type,
114                                                   referencedClass);
115
116             // Store the value in the corresponding variable.
117
variables.store(variableIndex++, value);
118
119             // Increment the variable index again for Category 2 values.
120
if (value.isCategory2())
121             {
122                 variableIndex++;
123             }
124         }
125     }
126
127
128     /**
129      * Exits the given method with the given return value.
130      */

131     public void exitMethod(Clazz clazz, Method method, Value returnValue)
132     {
133         setMethodReturnValue(clazz, method, returnValue);
134     }
135
136
137     /**
138      * Updates the given stack corresponding to the execution of the given
139      * field or method reference instruction.
140      */

141     public void invokeMember(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction, Stack stack)
142     {
143         int constantIndex = constantInstruction.constantIndex;
144
145         switch (constantInstruction.opcode)
146         {
147             case InstructionConstants.OP_GETSTATIC:
148                 isStatic = true;
149                 isLoad = true;
150                 break;
151
152             case InstructionConstants.OP_PUTSTATIC:
153                 isStatic = true;
154                 isLoad = false;
155                 break;
156
157             case InstructionConstants.OP_GETFIELD:
158                 isStatic = false;
159                 isLoad = true;
160                 break;
161
162             case InstructionConstants.OP_PUTFIELD:
163                 isStatic = false;
164                 isLoad = false;
165                 break;
166
167             case InstructionConstants.OP_INVOKESTATIC:
168                 isStatic = true;
169                 break;
170
171             case InstructionConstants.OP_INVOKEVIRTUAL:
172             case InstructionConstants.OP_INVOKESPECIAL:
173             case InstructionConstants.OP_INVOKEINTERFACE:
174                 isStatic = false;
175                 break;
176         }
177
178         // Pop the parameters and push the return value.
179
this.stack = stack;
180         clazz.constantPoolEntryAccept(constantIndex, this);
181         this.stack = null;
182     }
183
184
185     // Implementations for ConstantVisitor.
186

187     public void visitFieldrefConstant(Clazz clazz, FieldrefConstant fieldrefConstant)
188     {
189         // Pop the field value, if applicable.
190
if (!isLoad)
191         {
192             setFieldValue(clazz, fieldrefConstant, stack.pop());
193         }
194
195         // Pop the reference value, if applicable.
196
if (!isStatic)
197         {
198             setFieldClassValue(clazz, fieldrefConstant, stack.apop());
199         }
200
201         // Push the field value, if applicable.
202
if (isLoad)
203         {
204             String JavaDoc type = fieldrefConstant.getType(clazz);
205
206             stack.push(getFieldValue(clazz, fieldrefConstant, type));
207         }
208     }
209
210
211     public void visitAnyMethodrefConstant(Clazz clazz, RefConstant methodrefConstant)
212     {
213         String JavaDoc type = methodrefConstant.getType(clazz);
214
215         // Count the number of parameters.
216
int parameterCount = ClassUtil.internalMethodParameterCount(type);
217         if (!isStatic)
218         {
219             parameterCount++;
220         }
221
222         // Pop the parameters and the class reference, in reverse order.
223
for (int parameterIndex = parameterCount-1; parameterIndex >= 0; parameterIndex--)
224         {
225             setMethodParameterValue(clazz, methodrefConstant, parameterIndex, stack.pop());
226         }
227
228         // Pop the reference value, if applicable.
229
// Push the return value, if applicable.
230
String JavaDoc returnType = ClassUtil.internalMethodReturnType(type);
231         if (returnType.charAt(0) != ClassConstants.INTERNAL_TYPE_VOID)
232         {
233             stack.push(getMethodReturnValue(clazz, methodrefConstant, returnType));
234         }
235     }
236
237
238     protected void setFieldClassValue(Clazz clazz,
239                                       RefConstant refConstant,
240                                       ReferenceValue value)
241     {
242         // We don't care about the new value.
243
}
244
245
246     protected Value getFieldClassValue(Clazz clazz,
247                                        RefConstant refConstant,
248                                        String JavaDoc type)
249     {
250         // Try to figure out the class of the return type.
251
returnTypeClass = null;
252         refConstant.referencedMemberAccept(this);
253
254         return valueFactory.createValue(type,
255                                         returnTypeClass,
256                                         true);
257     }
258
259
260     protected void setFieldValue(Clazz clazz,
261                                  RefConstant refConstant,
262                                  Value value)
263     {
264         // We don't care about the new field value.
265
}
266
267
268     protected Value getFieldValue(Clazz clazz,
269                                   RefConstant refConstant,
270                                   String JavaDoc type)
271     {
272         // Try to figure out the class of the return type.
273
returnTypeClass = null;
274         refConstant.referencedMemberAccept(this);
275
276         return valueFactory.createValue(type,
277                                         returnTypeClass,
278                                         true);
279     }
280
281
282     protected void setMethodParameterValue(Clazz clazz,
283                                            RefConstant refConstant,
284                                            int parameterIndex,
285                                            Value value)
286     {
287         // We don't care about the parameter value.
288
}
289
290
291     protected Value getMethodParameterValue(Clazz clazz,
292                                             Method method,
293                                             int parameterIndex,
294                                             String JavaDoc type,
295                                             Clazz referencedClass)
296     {
297         return valueFactory.createValue(type, referencedClass, true);
298     }
299
300
301     protected void setMethodReturnValue(Clazz clazz,
302                                         Method method,
303                                         Value value)
304     {
305         // We don't care about the return value.
306
}
307
308
309     protected Value getMethodReturnValue(Clazz clazz,
310                                          RefConstant refConstant,
311                                          String JavaDoc type)
312     {
313         // Try to figure out the class of the return type.
314
returnTypeClass = null;
315         refConstant.referencedMemberAccept(this);
316
317         return valueFactory.createValue(type,
318                                         returnTypeClass,
319                                         true);
320     }
321
322
323     // Implementations for MemberVisitor.
324

325     public void visitProgramField(ProgramClass programClass, ProgramField programField)
326     {
327         returnTypeClass = programField.referencedClass;
328     }
329
330
331     public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
332     {
333         Clazz[] referencedClasses = programMethod.referencedClasses;
334         if (referencedClasses != null)
335         {
336             returnTypeClass = referencedClasses[referencedClasses.length - 1];
337         }
338     }
339
340
341     public void visitLibraryMember(LibraryClass libraryClass, LibraryMember libraryMember)
342     {
343         // Library members don't store the referenced classes.
344
}
345 }
346
Popular Tags