KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > proguard > classfile > instruction > ConstantInstruction


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.classfile.instruction;
22
23 import proguard.classfile.*;
24 import proguard.classfile.instruction.visitor.InstructionVisitor;
25 import proguard.classfile.attribute.*;
26 import proguard.classfile.constant.*;
27 import proguard.classfile.util.ClassUtil;
28 import proguard.classfile.constant.visitor.ConstantVisitor;
29
30 /**
31  * This Instruction represents an instruction that refers to an entry in the
32  * constant pool.
33  *
34  * @author Eric Lafortune
35  */

36 public class ConstantInstruction extends Instruction
37 implements ConstantVisitor
38 {
39     public int constantIndex;
40     public int constant;
41
42
43     // Fields acting as return parameters for the ConstantVisitor methods.
44
private int parameterStackDelta;
45     private int typeStackDelta;
46
47
48     /**
49      * Creates an uninitialized ConstantInstruction.
50      */

51     public ConstantInstruction() {}
52
53
54     /**
55      * Creates a new ConstantInstruction with the given opcode and constant pool
56      * index.
57      */

58     public ConstantInstruction(byte opcode, int constantIndex)
59     {
60         this(opcode, constantIndex, 0);
61     }
62
63
64     /**
65      * Creates a new ConstantInstruction with the given opcode, constant pool
66      * index, and constant.
67      */

68     public ConstantInstruction(byte opcode, int constantIndex, int constant)
69     {
70         this.opcode = opcode;
71         this.constantIndex = constantIndex;
72         this.constant = constant;
73     }
74
75
76     /**
77      * Copies the given instruction into this instruction.
78      * @param constantInstruction the instruction to be copied.
79      * @return this instruction.
80      */

81     public ConstantInstruction copy(ConstantInstruction constantInstruction)
82     {
83         this.opcode = constantInstruction.opcode;
84         this.constantIndex = constantInstruction.constantIndex;
85         this.constant = constantInstruction.constant;
86
87         return this;
88     }
89
90
91     // Implementations for Instruction.
92

93     public byte canonicalOpcode()
94     {
95         // Remove the _w extension, if any.
96
switch (opcode)
97         {
98             case InstructionConstants.OP_LDC_W:
99             case InstructionConstants.OP_LDC2_W: return InstructionConstants.OP_LDC;
100
101             default: return opcode;
102         }
103     }
104
105     public Instruction shrink()
106     {
107         // Do we need a short index or a long index?
108
if (requiredConstantIndexSize() == 1)
109         {
110             // Can we replace the long instruction by a short instruction?
111
if (opcode == InstructionConstants.OP_LDC_W)
112             {
113                 opcode = InstructionConstants.OP_LDC;
114             }
115         }
116         else
117         {
118             // Should we replace the short instruction by a long instruction?
119
if (opcode == InstructionConstants.OP_LDC)
120             {
121                 opcode = InstructionConstants.OP_LDC_W;
122             }
123         }
124
125         return this;
126     }
127
128     protected void readInfo(byte[] code, int offset)
129     {
130         int constantIndexSize = constantIndexSize();
131         int constantSize = constantSize();
132
133         constantIndex = readValue(code, offset, constantIndexSize); offset += constantIndexSize;
134         constant = readValue(code, offset, constantSize);
135     }
136
137
138     protected void writeInfo(byte[] code, int offset)
139     {
140         int constantIndexSize = constantIndexSize();
141         int constantSize = constantSize();
142
143         if (requiredConstantIndexSize() > constantIndexSize)
144         {
145             throw new IllegalArgumentException JavaDoc("Instruction has invalid constant index size ("+this.toString(offset)+")");
146         }
147
148         writeValue(code, offset, constantIndex, constantIndexSize); offset += constantIndexSize;
149         writeValue(code, offset, constant, constantSize);
150     }
151
152
153     public int length(int offset)
154     {
155         return 1 + constantIndexSize() + constantSize();
156     }
157
158
159     public void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, InstructionVisitor instructionVisitor)
160     {
161         instructionVisitor.visitConstantInstruction(clazz, method, codeAttribute, offset, this);
162     }
163
164
165     public int stackPopCount(Clazz clazz)
166     {
167         int stackPopCount = super.stackPopCount(clazz);
168
169         // Some special cases.
170
switch (opcode)
171         {
172             case InstructionConstants.OP_MULTIANEWARRAY:
173                 // For each dimension, an integer size is popped from the stack.
174
stackPopCount += constant;
175                 break;
176
177             case InstructionConstants.OP_PUTSTATIC:
178             case InstructionConstants.OP_PUTFIELD:
179                 // The field value is be popped from the stack.
180
clazz.constantPoolEntryAccept(constantIndex, this);
181                 stackPopCount += typeStackDelta;
182                 break;
183
184             case InstructionConstants.OP_INVOKEVIRTUAL:
185             case InstructionConstants.OP_INVOKESPECIAL:
186             case InstructionConstants.OP_INVOKESTATIC:
187             case InstructionConstants.OP_INVOKEINTERFACE:
188                 // The some parameters may be popped from the stack.
189
clazz.constantPoolEntryAccept(constantIndex, this);
190                 stackPopCount += parameterStackDelta;
191                 break;
192         }
193
194         return stackPopCount;
195     }
196
197
198     public int stackPushCount(Clazz clazz)
199     {
200         int stackPushCount = super.stackPushCount(clazz);
201
202         // Some special cases.
203
switch (opcode)
204         {
205             case InstructionConstants.OP_GETSTATIC:
206             case InstructionConstants.OP_GETFIELD:
207             case InstructionConstants.OP_INVOKEVIRTUAL:
208             case InstructionConstants.OP_INVOKESPECIAL:
209             case InstructionConstants.OP_INVOKESTATIC:
210             case InstructionConstants.OP_INVOKEINTERFACE:
211                 // The field value or a return value may be pushed onto the stack.
212
clazz.constantPoolEntryAccept(constantIndex, this);
213                 stackPushCount += typeStackDelta;
214                 break;
215         }
216
217         return stackPushCount;
218     }
219
220
221     // Implementations for ConstantVisitor.
222

223     public void visitIntegerConstant(Clazz clazz, IntegerConstant integerConstant) {}
224     public void visitLongConstant(Clazz clazz, LongConstant longConstant) {}
225     public void visitFloatConstant(Clazz clazz, FloatConstant floatConstant) {}
226     public void visitDoubleConstant(Clazz clazz, DoubleConstant doubleConstant) {}
227     public void visitStringConstant(Clazz clazz, StringConstant stringConstant) {}
228     public void visitUtf8Constant(Clazz clazz, Utf8Constant utf8Constant) {}
229     public void visitClassConstant(Clazz clazz, ClassConstant classConstant) {}
230     public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant) {}
231
232
233     public void visitFieldrefConstant(Clazz clazz, FieldrefConstant fieldrefConstant)
234     {
235         String JavaDoc type = fieldrefConstant.getType(clazz);
236
237         typeStackDelta = ClassUtil.internalTypeSize(ClassUtil.internalMethodReturnType(type));
238     }
239
240
241     public void visitInterfaceMethodrefConstant(Clazz clazz, InterfaceMethodrefConstant interfaceMethodrefConstant)
242     {
243         visitRefConstant(clazz, interfaceMethodrefConstant);
244     }
245
246
247     public void visitMethodrefConstant(Clazz clazz, MethodrefConstant methodrefConstant)
248     {
249         visitRefConstant(clazz, methodrefConstant);
250     }
251
252
253     private void visitRefConstant(Clazz clazz, RefConstant methodrefConstant)
254     {
255         String JavaDoc type = methodrefConstant.getType(clazz);
256
257         parameterStackDelta = ClassUtil.internalMethodParameterSize(type);
258         typeStackDelta = ClassUtil.internalTypeSize(ClassUtil.internalMethodReturnType(type));
259     }
260
261
262     // Implementations for Object.
263

264     public String JavaDoc toString()
265     {
266         return getName()+" #"+constantIndex;
267     }
268
269
270     // Small utility methods.
271

272     /**
273      * Returns the constant pool index size for this instruction.
274      */

275     private int constantIndexSize()
276     {
277         return opcode == InstructionConstants.OP_LDC ? 1 :
278                                                        2;
279     }
280
281
282     /**
283      * Returns the constant size for this instruction.
284      */

285     private int constantSize()
286     {
287         return opcode == InstructionConstants.OP_MULTIANEWARRAY ? 1 :
288                opcode == InstructionConstants.OP_INVOKEINTERFACE ? 2 :
289                                                                    0;
290     }
291
292
293     /**
294      * Computes the required constant pool index size for this instruction's
295      * constant pool index.
296      */

297     private int requiredConstantIndexSize()
298     {
299         return (constantIndex & 0xff) == constantIndex ? 1 :
300                (constantIndex & 0xffff) == constantIndex ? 2 :
301                                                            4;
302     }
303 }
304
Popular Tags