KickJava   Java API By Example, From Geeks To Geeks.

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


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 a simple instruction without variable arguments
29  * or constant pool references.
30  *
31  * @author Eric Lafortune
32  */

33 public class SimpleInstruction extends Instruction
34 {
35     public int constant;
36
37
38     /**
39      * Creates an uninitialized SimpleInstruction.
40      */

41     public SimpleInstruction() {}
42
43
44     /**
45      * Creates a new SimpleInstruction with the given opcode.
46      */

47     public SimpleInstruction(byte opcode)
48     {
49         this(opcode, embeddedConstant(opcode));
50     }
51
52
53     /**
54      * Creates a new SimpleInstruction with the given opcode and constant.
55      */

56     public SimpleInstruction(byte opcode, int constant)
57     {
58         this.opcode = opcode;
59         this.constant = constant;
60     }
61
62
63     /**
64      * Copies the given instruction into this instruction.
65      * @param simpleInstruction the instruction to be copied.
66      * @return this instruction.
67      */

68     public SimpleInstruction copy(SimpleInstruction simpleInstruction)
69     {
70         this.opcode = simpleInstruction.opcode;
71         this.constant = simpleInstruction.constant;
72
73         return this;
74     }
75
76
77     /**
78      * Return the embedded constant of the given opcode, or 0 if the opcode
79      * doesn't have one.
80      */

81     private static int embeddedConstant(byte opcode)
82     {
83         switch (opcode)
84         {
85             case InstructionConstants.OP_ICONST_M1: return -1;
86
87             case InstructionConstants.OP_ICONST_1:
88             case InstructionConstants.OP_LCONST_1:
89             case InstructionConstants.OP_FCONST_1:
90             case InstructionConstants.OP_DCONST_1: return 1;
91
92             case InstructionConstants.OP_ICONST_2:
93             case InstructionConstants.OP_FCONST_2: return 2;
94
95             case InstructionConstants.OP_ICONST_3: return 3;
96
97             case InstructionConstants.OP_ICONST_4: return 4;
98
99             case InstructionConstants.OP_ICONST_5: return 5;
100
101             default: return 0;
102         }
103     }
104
105
106     // Implementations for Instruction.
107

108     public byte canonicalOpcode()
109     {
110         // Replace any _1, _2, _3,... extension by _0.
111
switch (opcode)
112         {
113             case InstructionConstants.OP_ICONST_M1:
114             case InstructionConstants.OP_ICONST_0:
115             case InstructionConstants.OP_ICONST_1:
116             case InstructionConstants.OP_ICONST_2:
117             case InstructionConstants.OP_ICONST_3:
118             case InstructionConstants.OP_ICONST_4:
119             case InstructionConstants.OP_ICONST_5:
120             case InstructionConstants.OP_BIPUSH:
121             case InstructionConstants.OP_SIPUSH: return InstructionConstants.OP_ICONST_0;
122
123             case InstructionConstants.OP_LCONST_0:
124             case InstructionConstants.OP_LCONST_1: return InstructionConstants.OP_LCONST_0;
125
126             case InstructionConstants.OP_FCONST_0:
127             case InstructionConstants.OP_FCONST_1:
128             case InstructionConstants.OP_FCONST_2: return InstructionConstants.OP_FCONST_0;
129
130             case InstructionConstants.OP_DCONST_0:
131             case InstructionConstants.OP_DCONST_1: return InstructionConstants.OP_DCONST_0;
132
133             default: return opcode;
134         }
135     }
136
137     public Instruction shrink()
138     {
139         // Is this a sipush instruction that can be a bipush instruction?
140
if (opcode == InstructionConstants.OP_SIPUSH &&
141             constant << 24 >> 24 == constant)
142         {
143             opcode = InstructionConstants.OP_BIPUSH;
144         }
145
146         // Is this a bipush instruction that can be an iconst instruction?
147
if (opcode == InstructionConstants.OP_BIPUSH &&
148             constant >= -1 &&
149             constant <= 5)
150         {
151             opcode = (byte)(InstructionConstants.OP_ICONST_0 + constant);
152         }
153
154         return this;
155     }
156
157     protected void readInfo(byte[] code, int offset)
158     {
159         int constantSize = constantSize();
160
161         // Also initialize embedded constants that are different from 0.
162
constant = constantSize == 0 ?
163             embeddedConstant(opcode) :
164             readSignedValue(code, offset, constantSize);
165     }
166
167
168     protected void writeInfo(byte[] code, int offset)
169     {
170         int constantSize = constantSize();
171
172         if (requiredConstantSize() > constantSize)
173         {
174             throw new IllegalArgumentException JavaDoc("Instruction has invalid constant size ("+this.toString(offset)+")");
175         }
176
177         writeSignedValue(code, offset, constant, constantSize);
178     }
179
180
181     public int length(int offset)
182     {
183         return 1 + constantSize();
184     }
185
186
187     public void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, InstructionVisitor instructionVisitor)
188     {
189         instructionVisitor.visitSimpleInstruction(clazz, method, codeAttribute, offset, this);
190     }
191
192
193     // Implementations for Object.
194

195     public String JavaDoc toString()
196     {
197         return getName() +
198                (constantSize() > 0 ? " "+constant : "");
199     }
200
201
202     // Small utility methods.
203

204     /**
205      * Returns the constant size for this instruction.
206      */

207     private int constantSize()
208     {
209         return opcode == InstructionConstants.OP_BIPUSH ||
210                opcode == InstructionConstants.OP_NEWARRAY ? 1 :
211                opcode == InstructionConstants.OP_SIPUSH ? 2 :
212                                                             0;
213     }
214
215
216     /**
217      * Computes the required constant size for this instruction.
218      */

219     private int requiredConstantSize()
220     {
221         return constant >= -1 && constant <= 5 ? 0 :
222                constant << 24 >> 24 == constant ? 1 :
223                constant << 16 >> 16 == constant ? 2 :
224                                                   4;
225     }
226 }
227
Popular Tags