KickJava   Java API By Example, From Geeks To Geeks.

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


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
27 /**
28  * This Instruction represents an instruction that refers to a variable on the
29  * local variable stack.
30  *
31  * @author Eric Lafortune
32  */

33 public class VariableInstruction extends Instruction
34 {
35     public boolean wide;
36     public int variableIndex;
37     public int constant;
38
39
40     /**
41      * Creates an uninitialized VariableInstruction.
42      */

43     public VariableInstruction() {}
44
45
46     public VariableInstruction(boolean wide)
47     {
48         this.wide = wide;
49     }
50
51
52     public VariableInstruction(byte opcode)
53     {
54         this(opcode, embeddedVariable(opcode), 0);
55     }
56
57
58     public VariableInstruction(byte opcode,
59                                int variableIndex)
60     {
61         this(opcode, variableIndex, 0);
62     }
63
64
65     public VariableInstruction(byte opcode,
66                                int variableIndex,
67                                int constant)
68     {
69         this.opcode = opcode;
70         this.variableIndex = variableIndex;
71         this.constant = constant;
72         this.wide = requiredVariableIndexSize() > 1 ||
73                              requiredConstantSize() > 1;
74     }
75
76
77     /**
78      * Copies the given instruction into this instruction.
79      * @param variableInstruction the instruction to be copied.
80      * @return this instruction.
81      */

82     public VariableInstruction copy(VariableInstruction variableInstruction)
83     {
84         this.opcode = variableInstruction.opcode;
85         this.variableIndex = variableInstruction.variableIndex;
86         this.constant = variableInstruction.constant;
87         this.wide = variableInstruction.wide;
88
89         return this;
90     }
91
92
93     /**
94      * Return the embedded variable of the given opcode, or 0 if the opcode
95      * doesn't have one.
96      */

97     private static int embeddedVariable(byte opcode)
98     {
99         switch (opcode)
100         {
101             case InstructionConstants.OP_ILOAD_1:
102             case InstructionConstants.OP_LLOAD_1:
103             case InstructionConstants.OP_FLOAD_1:
104             case InstructionConstants.OP_DLOAD_1:
105             case InstructionConstants.OP_ALOAD_1:
106             case InstructionConstants.OP_ISTORE_1:
107             case InstructionConstants.OP_LSTORE_1:
108             case InstructionConstants.OP_FSTORE_1:
109             case InstructionConstants.OP_DSTORE_1:
110             case InstructionConstants.OP_ASTORE_1: return 1;
111
112             case InstructionConstants.OP_ILOAD_2:
113             case InstructionConstants.OP_LLOAD_2:
114             case InstructionConstants.OP_FLOAD_2:
115             case InstructionConstants.OP_DLOAD_2:
116             case InstructionConstants.OP_ALOAD_2:
117             case InstructionConstants.OP_ISTORE_2:
118             case InstructionConstants.OP_LSTORE_2:
119             case InstructionConstants.OP_FSTORE_2:
120             case InstructionConstants.OP_DSTORE_2:
121             case InstructionConstants.OP_ASTORE_2: return 2;
122
123             case InstructionConstants.OP_ILOAD_3:
124             case InstructionConstants.OP_LLOAD_3:
125             case InstructionConstants.OP_FLOAD_3:
126             case InstructionConstants.OP_DLOAD_3:
127             case InstructionConstants.OP_ALOAD_3:
128             case InstructionConstants.OP_ISTORE_3:
129             case InstructionConstants.OP_LSTORE_3:
130             case InstructionConstants.OP_FSTORE_3:
131             case InstructionConstants.OP_DSTORE_3:
132             case InstructionConstants.OP_ASTORE_3: return 3;
133
134             default: return 0;
135         }
136     }
137
138
139     /**
140      * Returns whether this instruction loads the value of a variable.
141      * The value is true for the ret instruction, but false for the iinc
142      * instruction.
143      */

144     public boolean isLoad()
145     {
146         // A load instruction can be recognized as follows. Note that this
147
// includes the ret instruction, which has a negative opcode.
148
return opcode < InstructionConstants.OP_ISTORE &&
149                opcode != InstructionConstants.OP_IINC;
150     }
151
152
153     // Implementations for Instruction.
154

155     public byte canonicalOpcode()
156     {
157         // Remove the _0, _1, _2, _3 extension, if any.
158
switch (opcode)
159         {
160             case InstructionConstants.OP_ILOAD_0:
161             case InstructionConstants.OP_ILOAD_1:
162             case InstructionConstants.OP_ILOAD_2:
163             case InstructionConstants.OP_ILOAD_3: return InstructionConstants.OP_ILOAD;
164             case InstructionConstants.OP_LLOAD_0:
165             case InstructionConstants.OP_LLOAD_1:
166             case InstructionConstants.OP_LLOAD_2:
167             case InstructionConstants.OP_LLOAD_3: return InstructionConstants.OP_LLOAD;
168             case InstructionConstants.OP_FLOAD_0:
169             case InstructionConstants.OP_FLOAD_1:
170             case InstructionConstants.OP_FLOAD_2:
171             case InstructionConstants.OP_FLOAD_3: return InstructionConstants.OP_FLOAD;
172             case InstructionConstants.OP_DLOAD_0:
173             case InstructionConstants.OP_DLOAD_1:
174             case InstructionConstants.OP_DLOAD_2:
175             case InstructionConstants.OP_DLOAD_3: return InstructionConstants.OP_DLOAD;
176             case InstructionConstants.OP_ALOAD_0:
177             case InstructionConstants.OP_ALOAD_1:
178             case InstructionConstants.OP_ALOAD_2:
179             case InstructionConstants.OP_ALOAD_3: return InstructionConstants.OP_ALOAD;
180
181             case InstructionConstants.OP_ISTORE_0:
182             case InstructionConstants.OP_ISTORE_1:
183             case InstructionConstants.OP_ISTORE_2:
184             case InstructionConstants.OP_ISTORE_3: return InstructionConstants.OP_ISTORE;
185             case InstructionConstants.OP_LSTORE_0:
186             case InstructionConstants.OP_LSTORE_1:
187             case InstructionConstants.OP_LSTORE_2:
188             case InstructionConstants.OP_LSTORE_3: return InstructionConstants.OP_LSTORE;
189             case InstructionConstants.OP_FSTORE_0:
190             case InstructionConstants.OP_FSTORE_1:
191             case InstructionConstants.OP_FSTORE_2:
192             case InstructionConstants.OP_FSTORE_3: return InstructionConstants.OP_FSTORE;
193             case InstructionConstants.OP_DSTORE_0:
194             case InstructionConstants.OP_DSTORE_1:
195             case InstructionConstants.OP_DSTORE_2:
196             case InstructionConstants.OP_DSTORE_3: return InstructionConstants.OP_DSTORE;
197             case InstructionConstants.OP_ASTORE_0:
198             case InstructionConstants.OP_ASTORE_1:
199             case InstructionConstants.OP_ASTORE_2:
200             case InstructionConstants.OP_ASTORE_3: return InstructionConstants.OP_ASTORE;
201
202             default: return opcode;
203         }
204     }
205
206     public Instruction shrink()
207     {
208         opcode = canonicalOpcode();
209
210         // Is this instruction pointing to a variable with index from 0 to 3?
211
if (variableIndex <= 3)
212         {
213             switch (opcode)
214             {
215                 case InstructionConstants.OP_ILOAD: opcode = (byte)(InstructionConstants.OP_ILOAD_0 + variableIndex); break;
216                 case InstructionConstants.OP_LLOAD: opcode = (byte)(InstructionConstants.OP_LLOAD_0 + variableIndex); break;
217                 case InstructionConstants.OP_FLOAD: opcode = (byte)(InstructionConstants.OP_FLOAD_0 + variableIndex); break;
218                 case InstructionConstants.OP_DLOAD: opcode = (byte)(InstructionConstants.OP_DLOAD_0 + variableIndex); break;
219                 case InstructionConstants.OP_ALOAD: opcode = (byte)(InstructionConstants.OP_ALOAD_0 + variableIndex); break;
220
221                 case InstructionConstants.OP_ISTORE: opcode = (byte)(InstructionConstants.OP_ISTORE_0 + variableIndex); break;
222                 case InstructionConstants.OP_LSTORE: opcode = (byte)(InstructionConstants.OP_LSTORE_0 + variableIndex); break;
223                 case InstructionConstants.OP_FSTORE: opcode = (byte)(InstructionConstants.OP_FSTORE_0 + variableIndex); break;
224                 case InstructionConstants.OP_DSTORE: opcode = (byte)(InstructionConstants.OP_DSTORE_0 + variableIndex); break;
225                 case InstructionConstants.OP_ASTORE: opcode = (byte)(InstructionConstants.OP_ASTORE_0 + variableIndex); break;
226             }
227         }
228
229         // Only make the instruction wide if necessary.
230
wide = requiredVariableIndexSize() > 1 ||
231                requiredConstantSize() > 1;
232
233         return this;
234     }
235
236
237     protected boolean isWide()
238     {
239         return wide;
240     }
241
242
243     protected void readInfo(byte[] code, int offset)
244     {
245         int variableIndexSize = variableIndexSize();
246         int constantSize = constantSize();
247
248         // Also initialize embedded variable indexes.
249
if (variableIndexSize == 0)
250         {
251             // An embedded variable index can be decoded as follows.
252
variableIndex = opcode < InstructionConstants.OP_ISTORE_0 ?
253                 (opcode - InstructionConstants.OP_ILOAD_0 ) & 3 :
254                 (opcode - InstructionConstants.OP_ISTORE_0) & 3;
255         }
256         else
257         {
258             variableIndex = readValue(code, offset, variableIndexSize); offset += variableIndexSize;
259         }
260
261         constant = readSignedValue(code, offset, constantSize);
262     }
263
264
265     protected void writeInfo(byte[] code, int offset)
266     {
267         int variableIndexSize = variableIndexSize();
268         int constantSize = constantSize();
269
270         if (requiredVariableIndexSize() > variableIndexSize)
271         {
272             throw new IllegalArgumentException JavaDoc("Instruction has invalid variable index size ("+this.toString(offset)+")");
273         }
274
275         if (requiredConstantSize() > constantSize)
276         {
277             throw new IllegalArgumentException JavaDoc("Instruction has invalid constant size ("+this.toString(offset)+")");
278         }
279
280         writeValue(code, offset, variableIndex, variableIndexSize); offset += variableIndexSize;
281         writeSignedValue(code, offset, constant, constantSize);
282     }
283
284
285     public int length(int offset)
286     {
287         return (wide ? 2 : 1) + variableIndexSize() + constantSize();
288     }
289
290
291     public void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, InstructionVisitor instructionVisitor)
292     {
293         instructionVisitor.visitVariableInstruction(clazz, method, codeAttribute, offset, this);
294     }
295
296
297     // Implementations for Object.
298

299     public String JavaDoc toString()
300     {
301         return getName() +
302                (wide ? "_w" : "") +
303                " v"+variableIndex +
304                (constantSize() > 0 ? ", "+constant : "");
305     }
306
307
308     // Small utility methods.
309

310     /**
311      * Returns the variable index size for this instruction.
312      */

313     private int variableIndexSize()
314     {
315         return (opcode >= InstructionConstants.OP_ILOAD_0 &&
316                 opcode <= InstructionConstants.OP_ALOAD_3) ||
317                (opcode >= InstructionConstants.OP_ISTORE_0 &&
318                 opcode <= InstructionConstants.OP_ASTORE_3) ? 0 :
319                wide ? 2 :
320                                                               1;
321     }
322
323
324     /**
325      * Computes the required variable index size for this instruction's variable
326      * index.
327      */

328     private int requiredVariableIndexSize()
329     {
330         return (variableIndex & 0x3) == variableIndex ? 0 :
331                (variableIndex & 0xff) == variableIndex ? 1 :
332                (variableIndex & 0xffff) == variableIndex ? 2 :
333                                                            4;
334
335     }
336
337
338     /**
339      * Returns the constant size for this instruction.
340      */

341     private int constantSize()
342     {
343         return opcode != InstructionConstants.OP_IINC ? 0 :
344                wide ? 2 :
345                                                         1;
346     }
347
348
349     /**
350      * Computes the required constant size for this instruction's constant.
351      */

352     private int requiredConstantSize()
353     {
354         return opcode != InstructionConstants.OP_IINC ? 0 :
355                constant << 24 >> 24 == constant ? 1 :
356                constant << 16 >> 16 == constant ? 2 :
357                                                         4;
358     }
359 }
360
Popular Tags