1 package serp.bytecode;
2
3 import java.io.*;
4
5 import serp.bytecode.visitor.*;
6
7
8
9
10
11
12
13
14 public class WideInstruction extends LocalVariableInstruction {
15 private static final Class[][] _mappings = new Class[][] {
16 { byte.class, int.class },
17 { boolean.class, int.class },
18 { char.class, int.class },
19 { short.class, int.class },
20 { void.class, int.class },
21 };
22 private int _ins = Constants.NOP;
23 private int _inc = -1;
24
25 WideInstruction(Code owner) {
26 super(owner, Constants.WIDE);
27 }
28
29 int getLength() {
30
31 int length = super.getLength() + 1 + 2;
32
33
34 if (_ins == Constants.IINC)
35 length += 2;
36 return length;
37 }
38
39 public int getStackChange() {
40 switch (_ins) {
41 case Constants.ILOAD:
42 case Constants.FLOAD:
43 case Constants.ALOAD:
44 return 1;
45 case Constants.LLOAD:
46 case Constants.DLOAD:
47 return 2;
48 case Constants.ISTORE:
49 case Constants.FSTORE:
50 case Constants.ASTORE:
51 return -1;
52 case Constants.LSTORE:
53 case Constants.DSTORE:
54 return -2;
55 default:
56 return 0;
57 }
58 }
59
60 public int getLogicalStackChange() {
61 switch (_ins) {
62 case Constants.ILOAD:
63 case Constants.FLOAD:
64 case Constants.ALOAD:
65 case Constants.LLOAD:
66 case Constants.DLOAD:
67 return 1;
68 case Constants.ISTORE:
69 case Constants.FSTORE:
70 case Constants.ASTORE:
71 case Constants.LSTORE:
72 case Constants.DSTORE:
73 return -1;
74 default:
75 return 0;
76 }
77 }
78
79 public String getTypeName() {
80 switch (_ins) {
81 case Constants.ILOAD:
82 case Constants.ISTORE:
83 return int.class.getName();
84 case Constants.LLOAD:
85 case Constants.LSTORE:
86 return long.class.getName();
87 case Constants.FLOAD:
88 case Constants.FSTORE:
89 return float.class.getName();
90 case Constants.DLOAD:
91 case Constants.DSTORE:
92 return double.class.getName();
93 case Constants.ALOAD:
94 case Constants.ASTORE:
95 return Object.class.getName();
96 default:
97 return null;
98 }
99 }
100
101 public TypedInstruction setType(String type) {
102 type = mapType(type, _mappings, true);
103 switch (_ins) {
104 case Constants.ILOAD:
105 case Constants.LLOAD:
106 case Constants.FLOAD:
107 case Constants.DLOAD:
108 case Constants.ALOAD:
109 if (type == null)
110 throw new IllegalStateException();
111 switch (type.charAt(0)) {
112 case 'i':
113 return (TypedInstruction) setInstruction(Constants.ILOAD);
114 case 'l':
115 return (TypedInstruction) setInstruction(Constants.LLOAD);
116 case 'f':
117 return (TypedInstruction) setInstruction(Constants.FLOAD);
118 case 'd':
119 return (TypedInstruction) setInstruction(Constants.DLOAD);
120 default:
121 return (TypedInstruction) setInstruction(Constants.ALOAD);
122 }
123 case Constants.ISTORE:
124 case Constants.LSTORE:
125 case Constants.FSTORE:
126 case Constants.DSTORE:
127 case Constants.ASTORE:
128 if (type == null)
129 throw new IllegalStateException();
130 switch (type.charAt(0)) {
131 case 'i':
132 return (TypedInstruction) setInstruction(Constants.ISTORE);
133 case 'l':
134 return (TypedInstruction) setInstruction(Constants.LSTORE);
135 case 'f':
136 return (TypedInstruction) setInstruction(Constants.FSTORE);
137 case 'd':
138 return (TypedInstruction) setInstruction(Constants.DSTORE);
139 default:
140 return (TypedInstruction) setInstruction(Constants.ASTORE);
141 }
142 default:
143 if (type != null)
144 throw new IllegalStateException("Augmented instruction not "
145 + "typed");
146 return this;
147 }
148 }
149
150
151
152
153
154 public int getInstruction() {
155 return _ins;
156 }
157
158
159
160
161 public WideInstruction setInstruction(Instruction ins) {
162 if (ins == null)
163 return setInstruction(Constants.NOP);
164 setInstruction(ins.getOpcode());
165 if (_ins == Constants.IINC)
166 _inc = ((IIncInstruction) ins).getIncrement();
167 return this;
168 }
169
170
171
172
173 public WideInstruction setInstruction(int opcode) {
174 int len = getLength();
175 _ins = opcode;
176 if (len != getLength())
177 invalidateByteIndexes();
178 return this;
179 }
180
181
182
183
184
185
186 public WideInstruction iinc() {
187 return setInstruction(Constants.IINC);
188 }
189
190
191
192
193
194
195 public WideInstruction ret() {
196 return setInstruction(Constants.RET);
197 }
198
199
200
201
202
203
204 public WideInstruction iload() {
205 return setInstruction(Constants.ILOAD);
206 }
207
208
209
210
211
212
213 public WideInstruction fload() {
214 return setInstruction(Constants.FLOAD);
215 }
216
217
218
219
220
221
222 public WideInstruction aload() {
223 return setInstruction(Constants.ALOAD);
224 }
225
226
227
228
229
230
231 public WideInstruction lload() {
232 return setInstruction(Constants.LLOAD);
233 }
234
235
236
237
238
239
240 public WideInstruction dload() {
241 return setInstruction(Constants.DLOAD);
242 }
243
244
245
246
247
248
249 public WideInstruction istore() {
250 return setInstruction(Constants.ISTORE);
251 }
252
253
254
255
256
257
258 public WideInstruction fstore() {
259 return setInstruction(Constants.FSTORE);
260 }
261
262
263
264
265
266
267 public WideInstruction astore() {
268 return setInstruction(Constants.ASTORE);
269 }
270
271
272
273
274
275
276 public WideInstruction lstore() {
277 return setInstruction(Constants.LSTORE);
278 }
279
280
281
282
283
284
285 public WideInstruction dstore() {
286 return setInstruction(Constants.DSTORE);
287 }
288
289
290
291
292
293 public int getIncrement() {
294 return _inc;
295 }
296
297
298
299
300
301
302 public WideInstruction setIncrement(int val) {
303 _inc = val;
304 return this;
305 }
306
307
308
309
310
311 public boolean equalsInstruction(Instruction other) {
312 if (other == this)
313 return true;
314 if (!super.equalsInstruction(other))
315 return false;
316 if (!(other instanceof WideInstruction))
317 return false;
318
319 WideInstruction ins = (WideInstruction) other;
320 int code = getInstruction();
321 int otherCode = ins.getInstruction();
322 if (code != otherCode)
323 return false;
324 if (code == Constants.IINC) {
325 int inc = getIncrement();
326 int otherInc = ins.getIncrement();
327 return (inc == -1) || (otherInc == -1) || (inc == otherInc);
328 }
329 return true;
330 }
331
332 public void acceptVisit(BCVisitor visit) {
333 visit.enterWideInstruction(this);
334 visit.exitWideInstruction(this);
335 }
336
337 void read(Instruction orig) {
338 super.read(orig);
339 setInstruction(((WideInstruction) orig).getInstruction());
340 }
341
342 void read(DataInput in) throws IOException {
343 super.read(in);
344 _ins = in.readUnsignedByte();
345 setLocal(in.readUnsignedShort());
346 if (_ins == Constants.IINC)
347 _inc = in.readUnsignedShort();
348 }
349
350 void write(DataOutput out) throws IOException {
351 super.write(out);
352 out.writeByte(_ins);
353 out.writeShort(getLocal());
354 if (_ins == Constants.IINC)
355 out.writeShort(_inc);
356 }
357 }