KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > alt > jiapi > reflect > Instruction


1 /*
2  * Copyright (C) 2001 Mika Riekkinen, Joni Suominen
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  */

18
19 package alt.jiapi.reflect;
20
21 import java.util.HashMap JavaDoc;
22 import alt.jiapi.reflect.instruction.Opcodes;
23
24 /**
25  * This class represents an entry in InstructionList.
26  *
27  * @author Mika Riekkinen
28  * @author Joni Suominen
29  * @see InstructionList
30  * @version $Revision: 1.19 $ $Date: 2005/06/03 07:50:22 $
31  */

32 public class Instruction implements Cloneable JavaDoc {
33     /**
34      * Attributes are used to associate individual Instructions
35      * with any data they see fit.
36      */

37     private HashMap JavaDoc attributes;
38     /**
39      * The bytecode of an instruction.
40      */

41     private byte[] bytes;
42     /**
43      * Offset of the instruction in instruction list.
44      */

45     private short /*int*/ offset;
46
47     private static final short UNKNOWN_STACK_USAGE = 99;
48     /**
49      * This tables lists stack usages of each opcodes.
50      * Some opcodes has variable length stackusages.
51      * These these opcodes must have a higher level
52      * Instruction, which overrides stackUsage()
53      * method.
54      */

55     private static short[] stackUsages = new short[] {
56         0, // nop
57
1,1,1,1,1,1,1,1,
58         2,2, // LCONST_0, LCONST_1
59
1,1,1,
60         2,2, // DCONST_0, DCONST_1
61
1,1,1,1,
62         2, // LDC2_W
63
1,
64         2, // LLOAD
65
1,
66         2, // DLOAD
67
1,1,1,1,1,
68         2,2,2,2, // LLOAD_0, LLOAD_1, LLOAD_2, LLOAD_3
69
1,1,1,1,
70         1,1,1,1, // DLOAD_0, DLOAD_1, DLOAD_2, DLOAD_3
71
1,1,1,1, // last one is aload_3
72

73         -1,
74         0, // LALOAD
75
-1,
76         0, // DALOAD
77
-1,-1,-1,-1,-1,
78         -2, // LSTORE
79
-1,
80         -2, // DSTORE
81
-1,-1,-1,-1,-1,
82         -2,-2,-2,-2, // LSTORE_0, LSTORE_1, LSTORE_2, LSTORE_3
83
-1,-1,-1,-1,
84         -2,-2,-2,-2, // DSTORE_0, DSTORE_1, DSTORE_2, DSTORE_3
85
-1,-1,-1,-1,// last one is astore_3
86

87         -3,
88         -4, // LASTORE
89
-3,
90         -4, // DASTORE
91
-3,-3,-3,-3, // last one is sa_store
92
-1, // POP
93
-2, // POP2
94
1,1,1,2,2,2, // ??????? DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1, DUP2_X2
95
0, // swap
96

97         -1,
98         -2, // LADD
99
-1,
100         -2, // DADD
101
-1,
102         -2, // LSUB
103
-1,
104         -2, // DSUB
105
-1,
106         -2, // LMUL
107
-1,
108         -2, // DMUL
109
-1,
110         -2, // LDIV
111
-1,
112         -2, // DDIV
113
-1,
114         -2, // LREM
115
-1,
116         -2, // DREM
117
0,0,0,0, // dneg ----
118

119         // ok so far
120
-1,-1,-1,-1,-1,-1,-1,
121         -2, // LAND
122
-1,
123         -2, // LOR
124
-1,
125         -2, // LXOR
126
0, // IINC
127

128         1, // I2L
129
0,
130         1, // I2D
131
-1, // L2I
132
-1, // L2F
133
0,0,
134         1, // F2L
135
1, // F2D
136
-1, // D2I
137
0,
138         -1, // D2F
139
0,0,0, // I2S
140
// ---------------
141

142         -3, // LCMP
143
-1,-1,
144         -3, // DCMPL
145
-3, // DCMPG
146
-1,-1,-1,-1,-1,-1, // ifle
147
-2,-2,-2,-2,-2,-2,-2,-2, // IF_ACMPNE
148
0,1,0, // goto, jsr ,ret
149

150         -1,-1, // tableswitch, lookupswitch
151
-1,
152         -2, // LRETURN
153
-1,
154         -2, // DRETURN
155
-1, // areturn
156

157
158         // BUG: Instruction might both produce and consume stack
159
// getfield first consumes, then produces, etc. etc.
160
0,1,-1, 0,-2, // return, getstatic, putstatic, getfield, putfield ***
161
//0,1,-1, 0,-2, // return, ... putfield; Original - samples working
162

163
164         // BUG: Instruction might both produce and consume stack
165
// getfield first consumes, then produces, etc. etc.
166
// For the invocations, stack usage is calculated in
167
// Invocation.stackUsage().
168
UNKNOWN_STACK_USAGE, UNKNOWN_STACK_USAGE, // invokeXXX
169
UNKNOWN_STACK_USAGE, UNKNOWN_STACK_USAGE, // invokeXXX
170

171         0, 1,
172         0,0,0,0,0,0, // instanceof
173
-1,-1, // MONITOR_XXX
174

175         0, // WIDE ??????????????????
176
UNKNOWN_STACK_USAGE, // multinewarray ???????????????????
177

178         -1,-1,
179         0,1, // goto_w(200), jsr_w(201)
180
0, // breakpoint
181
0,0,0,0,0,0,0,0,0, // 210
182
0,0,0,0,0,0,0,0,0,0, // 220
183
0,0,0,0,0,0,0,0,0,0, // 230
184
0,0,0,0,0,0,0,0,0,0, // 240
185
0,0,0,0,0,0,0,0,0,0, // 250
186
0,0,0, // 253
187
0,0 // reserved: impdep1(254), impdep2(255)
188
};
189
190
191     /**
192      * This tables lists stack consumption of each opcodes.
193      * Some opcodes has variable length consumptions.
194      * These opcodes must have a higher level
195      * Instruction, which overrides stackConsumption()
196      * method.
197      */

198     private static short[] stackConsumptions = new short[] {
199         0, // nop
200
0,0,0,0,0,0,0,0,
201         0,0, // LCONST_0, LCONST_1
202
0,0,0,
203         0,0, // DCONST_0, DCONST_1
204
0,0,0,0,
205         0, // LDC2_W
206
0,
207         0, // LLOAD
208
0,
209         0, // DLOAD
210
0,0,0,0,0,
211         0,0,0,0, // LLOAD_0, LLOAD_1, LLOAD_2, LLOAD_3
212
0,0,0,0,
213         0,0,0,0, // DLOAD_0, DLOAD_1, DLOAD_2, DLOAD_3
214
0,0,0,0, // last one is aload_3
215

216         2,
217         2, // LALOAD
218
2,
219         2, // DALOAD
220
2,2,2,2,
221         1,
222         2, // LSTORE
223
1,
224         2, // DSTORE
225
1,1,1,1,1,
226         2,2,2,2, // LSTORE_0, LSTORE_1, LSTORE_2, LSTORE_3
227
1,1,1,1,
228         2,2,2,2, // DSTORE_0, DSTORE_1, DSTORE_2, DSTORE_3
229
1,1,1,1,// last one is astore_3
230

231         3,
232         4, // LASTORE
233
3,
234         4, // DASTORE
235
3,3,3,3, // last one is sa_store
236
1, // POP
237
2, // POP2
238
1,2,2,2,2,2, // ??????? DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1, DUP2_X2
239
2, // swap
240

241         2,
242         4, // LADD
243
2,
244         4, // DADD
245
2,
246         4, // LSUB
247
2,
248         4, // DSUB
249
2,
250         4, // LMUL
251
2,
252         4, // DMUL
253
2,
254         4, // LDIV
255
2,
256         4, // DDIV
257
2,
258         4, // LREM
259
2,
260         4, // DREM
261
1,2,1,2, // dneg ----
262

263         // ok so far
264
2,3,2,3,2,3,2,
265         4, // LAND
266
2,
267         4, // LOR
268
2,
269         4, // LXOR
270
0, // IINC
271

272         1, // I2L
273
1,
274         1, // I2D
275
2, // L2I
276
2, // L2F
277
2,2,
278         1, // F2L
279
1, // F2D
280
2, // D2I
281
2,
282         2, // D2F
283
1,1,1, // I2S
284
// ---------------
285

286         4, // LCMP
287
2,2,
288         4, // DCMPL
289
4, // DCMPG
290
1,1,1,1,1,1, // ifle
291
2,2,2,2,2,2,2,2, // IF_ACMPNE
292
0,0,0, // goto, jsr ,ret
293

294         1,1, // tableswitch, lookupswitch
295
1,
296         2, // LRETURN
297
1,
298         2, // DRETURN
299
1, // areturn
300

301         0,0,1,1,2, // return, getstatic, putstatic, getfield, putfield ***
302

303         UNKNOWN_STACK_USAGE, UNKNOWN_STACK_USAGE, // invokeXXX
304
UNKNOWN_STACK_USAGE, UNKNOWN_STACK_USAGE, // invokeXXX
305

306         0, 0, // XXXUNUSEDXXX, NEW
307
1,1,1,1,1,1, // instanceof
308
1,1, // MONITOR_XXX
309

310         0, // WIDE ??????????????????
311
UNKNOWN_STACK_USAGE, // multinewarray ???????????????????
312

313         1,1, // IFNULL, IFNONNULL
314
0,0, // goto_w(200), jsr_w(201)
315
0, // breakpoint
316
0,0,0,0,0,0,0,0,0, // 210
317
0,0,0,0,0,0,0,0,0,0, // 220
318
0,0,0,0,0,0,0,0,0,0, // 230
319
0,0,0,0,0,0,0,0,0,0, // 240
320
0,0,0,0,0,0,0,0,0,0, // 250
321
0,0,0, // 253
322
0,0 // reserved: impdep1(254), impdep2(255)
323
};
324
325 // static {
326
// System.out.println(stackUsages[0xff & Opcodes.IMPDEP2]);
327
// }
328

329
330
331     /**
332      * Special package protected constructor, that is
333      * used with TargetInstruction
334      */

335     Instruction() {
336     }
337
338
339     /**
340      * Constructor. Byte array given, must hold all the data
341      * for this Instruction. First byte must be the opcode
342      * of this Instruction.
343      *
344      * @param bytes Byte array representing this instruction. May
345      * not be null. Bytes must have at least one byte in it.
346      * @exception IllegalArgumentException is thrown, if byte[].length == 0
347      * @exception NullpointerException is thrown, if byte[] == null
348      */

349     public Instruction(byte[] bytes) {
350         if (bytes.length == 0) { // Makes implicit null check
351
throw new IllegalArgumentException JavaDoc("bytes.length of Instruction must be greater than 0");
352         }
353
354         this.bytes = bytes;
355     }
356
357
358     /**
359      * Set the bytes of this Instruction.
360      *
361      * @param bytes
362      */

363     protected void setBytes(byte[] bytes) {
364         // NOTE: Should be package protected???
365
this.bytes = bytes;
366     }
367
368     /**
369      * Gets the bytes of this instruction.
370      * First byte in array is its opcode.
371      *
372      * @return bytes of this instruction.
373      */

374     public byte[] getBytes() {
375         return bytes;
376     }
377
378     /**
379      * Gets the opcode of this Instruction.
380      * @return opcode of this instruction.
381      */

382     public byte getOpcode() {
383         return bytes[0];
384     }
385
386     /**
387      * Get the length of this instruction.
388      * This is the same as <code>getBytes().length</code>
389      */

390     public int length() {
391         return bytes.length;
392     }
393
394     public String JavaDoc toString() {
395         int opCode = getOpcode();
396         opCode = opCode & 0xff;
397         StringBuffer JavaDoc sb = new StringBuffer JavaDoc(Opcodes.opcodeStrings[opCode]);
398
399         for (int i = 1; i < bytes.length; i++) {
400             sb.append(" " + (0xff & bytes[i]));
401         }
402
403         return sb.toString();
404     }
405
406
407
408    /**
409      * Get the stack usage this Instruction uses. Negative stack usage
410      * means this Instruction consumes(pops) data from stack. Positive stack
411      * usage means this Instructions produces(pushes) data on stack.<p>
412      *
413      * Some instructions may both consume and produce data on stack.
414      * This method returns the total usage after instruction has been
415      * executed.
416      *
417      * @return Stack usage
418      */

419     public short stackUsage() {
420         short opcode = getOpcode();
421
422
423         // Check if opcode represents an instruction with variable length
424
// stack usage
425
if (opcode == Opcodes.INVOKEVIRTUAL) {
426             byte[] bytes = getBytes();
427             // return ...;
428

429             // BUG: for now, just pass through, and give a default
430
// value from stackUsages table. UNKNOWN_STACK_USAGE
431
}
432 // else if (...){
433
// }
434

435         return stackUsages[0xff & opcode];
436     }
437
438
439    /**
440      * Get the stack consumption of this Instruction. Stack consumption
441      * is allways positive, or zero, and indicates how many elements of data
442      * this instruction needs for its execution.
443      *
444      * @return Stack consumption
445      */

446     public short stackConsumption() {
447         short opcode = getOpcode();
448
449         // Check if opcode represents an instruction with variable length
450
// stack consumption
451
if (opcode == Opcodes.MULTIANEWARRAY) {
452             byte[] bytes = getBytes();
453             return bytes[3];
454         }
455
456         return stackConsumptions[0xff & opcode];
457     }
458
459
460
461     /**
462      * Sets the offset of this instruction.
463      * Offset is calculated as bytes from the beginning of the method.
464      */

465     protected void setOffset(short offset) {
466         this.offset = offset;
467     }
468
469     /**
470      * Gets the offset of this instruction.
471      * Offset is calculated as bytes from the beginning of the method.
472      */

473     protected short getOffset() {
474         return offset;
475     }
476
477     /**
478      * Sets a named attribute to this Instruction.
479      */

480     public void setAttribute(String JavaDoc name) {
481         setAttribute(name, "");
482     }
483
484
485     /**
486      * Sets a named attribute to this Instruction.
487      */

488     public void setAttribute(String JavaDoc name, Object JavaDoc value) {
489         if (attributes == null) {
490             attributes = new HashMap JavaDoc();
491         }
492         
493         attributes.put(name, value);
494     }
495
496
497     /**
498      * Gets a named attribute.
499      * @return null, if no such attribute is found
500      */

501     public Object JavaDoc getAttribute(String JavaDoc name) {
502         if (attributes == null) {
503             return null;
504         }
505         
506         return attributes.get(name);
507     }
508 }
509
510
511
512
Popular Tags