KickJava   Java API By Example, From Geeks To Geeks.

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


1 package alt.jiapi.reflect;
2
3 import java.util.List JavaDoc;
4 import java.util.LinkedList JavaDoc;
5
6 import alt.jiapi.file.ConstantPool;
7 import alt.jiapi.reflect.instruction.Opcodes;
8 import alt.jiapi.reflect.instruction.Invocation;
9 import alt.jiapi.reflect.instruction.FieldAccess;
10 import alt.jiapi.reflect.instruction.CPInstruction;
11
12 /**
13  * Class InstructionParser.
14  *
15  * @author Mika Riekkinen
16  */

17 class InstructionParser {
18     /**
19      * Parse bytecode and create a List of Instructions out
20      * of it.
21      *
22      * @param byteCode Bytecode to be parsed.
23      * @return a List of Instructions.
24      * @exception
25      */

26     List JavaDoc createInstructionList(byte[] byteCode, ConstantPool cp) {
27         List JavaDoc list = new LinkedList JavaDoc();
28         boolean branchesFound = false;
29
30         /*
31          * First loop through bytecode and create raw instructions.
32          * After loop, resolve branch/switch targets.
33          */

34         for (int i = 0; i < byteCode.length; i++) {
35             byte opcode = byteCode[i];
36             Instruction ins = null;
37             int iMod = 0;
38
39             //System.out.println("Instruction " + Opcodes.opcodeStrings[opcode&0xff]);
40
switch(opcode) {
41             case Opcodes.NOP:
42             case Opcodes.ACONST_NULL:
43             case Opcodes.ICONST_M1:
44             case Opcodes.ICONST_0:
45             case Opcodes.ICONST_1:
46             case Opcodes.ICONST_2:
47             case Opcodes.ICONST_3:
48             case Opcodes.ICONST_4:
49             case Opcodes.ICONST_5:
50             case Opcodes.LCONST_0:
51             case Opcodes.LCONST_1:
52             case Opcodes.FCONST_0:
53             case Opcodes.FCONST_1:
54             case Opcodes.FCONST_2:
55             case Opcodes.DCONST_0:
56             case Opcodes.DCONST_1:
57                 ins = new Instruction(new byte[] { byteCode[i] });
58                 break;
59             case Opcodes.BIPUSH:
60                 ins = new Instruction(new byte[] { byteCode[i],
61                                                    byteCode[i+1] });
62                 iMod = 1;//i++;
63
break;
64             case Opcodes.SIPUSH:
65                 ins = new Instruction(new byte[] { byteCode[i],
66                                                    byteCode[i+1],
67                                                    byteCode[i+2] });
68                 iMod = 2;//i += 2;
69
break;
70             case Opcodes.LDC:
71                 ins = new CPInstruction(new byte[] { byteCode[i],
72                                                      byteCode[i+1] }, cp);
73                 iMod = 1;//i++;
74
break;
75             case Opcodes.LDC_W:
76             case Opcodes.LDC2_W:
77                 ins = new CPInstruction(new byte[] { byteCode[i],
78                                                      byteCode[i+1],
79                                                      byteCode[i+2] }, cp);
80                 iMod = 2;//i += 2;
81
break;
82             case Opcodes.ILOAD:
83             case Opcodes.LLOAD:
84             case Opcodes.FLOAD:
85             case Opcodes.DLOAD:
86             case Opcodes.ALOAD:
87                 ins = new Instruction(new byte[] { byteCode[i],
88                                                    byteCode[i+1] });
89                 iMod = 1;//i++;
90
break;
91             case Opcodes.ILOAD_0:
92             case Opcodes.ILOAD_1:
93             case Opcodes.ILOAD_2:
94             case Opcodes.ILOAD_3:
95             case Opcodes.LLOAD_0:
96             case Opcodes.LLOAD_1:
97             case Opcodes.LLOAD_2:
98             case Opcodes.LLOAD_3:
99             case Opcodes.FLOAD_0:
100             case Opcodes.FLOAD_1:
101             case Opcodes.FLOAD_2:
102             case Opcodes.FLOAD_3:
103             case Opcodes.DLOAD_0:
104             case Opcodes.DLOAD_1:
105             case Opcodes.DLOAD_2:
106             case Opcodes.DLOAD_3:
107             case Opcodes.ALOAD_0:
108             case Opcodes.ALOAD_1:
109             case Opcodes.ALOAD_2:
110             case Opcodes.ALOAD_3:
111                 ins = new Instruction(new byte[] { byteCode[i] });
112                 break;
113             case Opcodes.IALOAD:
114             case Opcodes.LALOAD:
115             case Opcodes.FALOAD:
116             case Opcodes.DALOAD:
117             case Opcodes.AALOAD:
118             case Opcodes.BALOAD:
119             case Opcodes.CALOAD:
120             case Opcodes.SALOAD:
121                 ins = new Instruction(new byte[] { byteCode[i] });
122                 break;
123             case Opcodes.ISTORE:
124             case Opcodes.LSTORE:
125             case Opcodes.FSTORE:
126             case Opcodes.DSTORE:
127             case Opcodes.ASTORE:
128                 ins = new Instruction(new byte[] { byteCode[i],
129                                                    byteCode[i+1] });
130                 iMod = 1;//i++;
131
break;
132             case Opcodes.ISTORE_0:
133             case Opcodes.ISTORE_1:
134             case Opcodes.ISTORE_2:
135             case Opcodes.ISTORE_3:
136             case Opcodes.LSTORE_0:
137             case Opcodes.LSTORE_1:
138             case Opcodes.LSTORE_2:
139             case Opcodes.LSTORE_3:
140             case Opcodes.FSTORE_0:
141             case Opcodes.FSTORE_1:
142             case Opcodes.FSTORE_2:
143             case Opcodes.FSTORE_3:
144             case Opcodes.DSTORE_0:
145             case Opcodes.DSTORE_1:
146             case Opcodes.DSTORE_2:
147             case Opcodes.DSTORE_3:
148             case Opcodes.ASTORE_0:
149             case Opcodes.ASTORE_1:
150             case Opcodes.ASTORE_2:
151             case Opcodes.ASTORE_3:
152             case Opcodes.IASTORE:
153             case Opcodes.LASTORE:
154             case Opcodes.FASTORE:
155             case Opcodes.DASTORE:
156             case Opcodes.AASTORE:
157             case Opcodes.BASTORE:
158             case Opcodes.CASTORE:
159             case Opcodes.SASTORE:
160             case Opcodes.POP:
161             case Opcodes.POP2:
162             case Opcodes.DUP:
163             case Opcodes.DUP_X1:
164             case Opcodes.DUP_X2:
165             case Opcodes.DUP2:
166             case Opcodes.DUP2_X1:
167             case Opcodes.DUP2_X2:
168             case Opcodes.SWAP:
169             case Opcodes.IADD:
170             case Opcodes.LADD:
171             case Opcodes.FADD:
172             case Opcodes.DADD:
173             case Opcodes.ISUB:
174             case Opcodes.LSUB:
175             case Opcodes.FSUB:
176             case Opcodes.DSUB:
177             case Opcodes.IMUL:
178             case Opcodes.LMUL:
179             case Opcodes.FMUL:
180             case Opcodes.DMUL:
181             case Opcodes.IDIV:
182             case Opcodes.LDIV:
183             case Opcodes.FDIV:
184             case Opcodes.DDIV:
185             case Opcodes.IREM:
186             case Opcodes.LREM:
187             case Opcodes.FREM:
188             case Opcodes.DREM:
189             case Opcodes.INEG:
190             case Opcodes.LNEG:
191             case Opcodes.FNEG:
192             case Opcodes.DNEG:
193             case Opcodes.ISHL:
194             case Opcodes.LSHL:
195             case Opcodes.ISHR:
196             case Opcodes.LSHR:
197             case Opcodes.IUSHR:
198             case Opcodes.LUSHR:
199             case Opcodes.IAND:
200             case Opcodes.LAND:
201             case Opcodes.IOR:
202             case Opcodes.LOR:
203             case Opcodes.IXOR:
204             case Opcodes.LXOR:
205                 ins = new Instruction(new byte[] { byteCode[i] });
206                 break;
207             case Opcodes.IINC:
208                 ins = new Instruction(new byte[] { byteCode[i],
209                                                    byteCode[i+1],
210                                                    byteCode[i+2] });
211                 iMod = 2;//i += 2;
212
break;
213             case Opcodes.I2L:
214             case Opcodes.I2F:
215             case Opcodes.I2D:
216             case Opcodes.L2I:
217             case Opcodes.L2F:
218             case Opcodes.L2D:
219             case Opcodes.F2I:
220             case Opcodes.F2L:
221             case Opcodes.F2D:
222             case Opcodes.D2I:
223             case Opcodes.D2L:
224             case Opcodes.D2F:
225             case Opcodes.I2B:
226             case Opcodes.I2C:
227             case Opcodes.I2S:
228             case Opcodes.LCMP:
229             case Opcodes.FCMPL:
230             case Opcodes.FCMPG:
231             case Opcodes.DCMPL:
232             case Opcodes.DCMPG:
233                 ins = new Instruction(new byte[] { byteCode[i] });
234                 break;
235             case Opcodes.IFEQ:
236             case Opcodes.IFNE:
237             case Opcodes.IFLT:
238             case Opcodes.IFGE:
239             case Opcodes.IFGT:
240             case Opcodes.IFLE:
241             case Opcodes.IF_ICMPEQ:
242             case Opcodes.IF_ICMPNE:
243             case Opcodes.IF_ICMPLT:
244             case Opcodes.IF_ICMPGE:
245             case Opcodes.IF_ICMPGT:
246             case Opcodes.IF_ICMPLE:
247             case Opcodes.IF_ACMPEQ:
248             case Opcodes.IF_ACMPNE:
249             case Opcodes.GOTO:
250             case Opcodes.JSR:
251                 branchesFound = true;
252                 ins = new BranchInstruction(new byte[] { byteCode[i],
253                                                          byteCode[i+1],
254                                                          byteCode[i+2]});
255                 iMod = 2;//i += 2;
256
break;
257             case Opcodes.RET:
258                 ins = new Instruction(new byte[] { byteCode[i],
259                                                    byteCode[i+1]});
260                 iMod = 1;//i += 1;
261
break;
262             case Opcodes.TABLESWITCH:
263                 branchesFound = true;
264                 int tspCount = 3 - (i % 4);
265                 
266                 byte l1 = byteCode[i + tspCount + 5];
267                 byte l2 = byteCode[i + tspCount + 6];
268                 byte l3 = byteCode[i + tspCount + 7];
269                 byte l4 = byteCode[i + tspCount + 8];
270
271                 int low = (((int)l1) << 24) | (((int)l2) << 16) |
272                     (((int)l3) << 8) | l4;
273
274                 byte h1 = byteCode[i + tspCount + 9];
275                 byte h2 = byteCode[i + tspCount + 10];
276                 byte h3 = byteCode[i + tspCount + 11];
277                 byte h4 = byteCode[i + tspCount + 12];
278
279                 int high = (((int)h1) << 24) | (((int)h2) << 16) |
280                     (((int)h3) << 8) | h4;
281
282                 int size = high - low + 1;
283                 int bSize = size * 4; // Size of offset table in bytes
284

285                 byte[] tsBytes = new byte[13 + tspCount + bSize];
286                 for (int k = 0; k < tsBytes.length; k++) {
287                     tsBytes[k] = byteCode[i + k];
288                 }
289
290                 iMod = tsBytes.length -1;//i += tsBytes.length -1;
291
ins = new SwitchInstruction(tsBytes, tspCount, size);
292
293                 break;
294             case Opcodes.LOOKUPSWITCH:
295                 branchesFound = true;
296                 int pCount = 3 - (i % 4);
297                 // count padding
298
// NOTE: Following is a bug
299

300                 byte np1 = byteCode[i + pCount + 5];
301                 byte np2 = byteCode[i + pCount + 6];
302                 byte np3 = byteCode[i + pCount + 7];
303                 byte np4 = byteCode[i + pCount + 8];
304
305                 int nPairs = (np1 << 24) & 0xff000000 | (np2 << 16) & 0xff0000|
306                     (np3 << 8) & 0xff00 | (np4 & 0xff);
307
308                 int lbSize = nPairs * 4 * 2; // Size of offset table in bytes
309

310                 byte[] lsBytes = new byte[9 + pCount + lbSize ];
311
312                 for (int k = 0; k < lsBytes.length; k++) {
313                     lsBytes[k] = byteCode[i + k];
314                 }
315
316                 iMod = lsBytes.length -1;//i += lsBytes.length -1;
317
ins = new SwitchInstruction(lsBytes, pCount, nPairs);
318                 break;
319             case Opcodes.IRETURN:
320             case Opcodes.LRETURN:
321             case Opcodes.FRETURN:
322             case Opcodes.DRETURN:
323             case Opcodes.ARETURN:
324             case Opcodes.RETURN:
325                 ins = new Instruction(new byte[] { byteCode[i] });
326                 break;
327             case Opcodes.GETSTATIC:
328             case Opcodes.PUTSTATIC:
329             case Opcodes.GETFIELD:
330             case Opcodes.PUTFIELD:
331                 ins = new FieldAccess(new byte[] { byteCode[i],
332                                                    byteCode[i+1],
333                                                    byteCode[i+2]}, cp);
334                 iMod = 2;//i += 2;
335
break;
336             case Opcodes.INVOKEVIRTUAL:
337             case Opcodes.INVOKESPECIAL:
338             case Opcodes.INVOKESTATIC:
339                 // BUG: what is the stack consumption
340
// cp.getMethodDescriptor(....);
341
ins = new Invocation(new byte[] { byteCode[i],
342                                                   byteCode[i+1],
343                                                   byteCode[i+2] }, cp);
344                 iMod = 2;//i += 2;
345
break;
346             case Opcodes.INVOKEINTERFACE:
347                 byte count = byteCode[i+3];
348                 ins = new Invocation(new byte[] { byteCode[i],
349                                                   byteCode[i+1],
350                                                   byteCode[i+2],
351                                                   count,
352                                                   byteCode[i+4]}, cp);
353                 iMod = 4;//i += 4;
354
break;
355             case Opcodes.XXXUNUSEDXXX:
356                 new Instruction(new byte[] { byteCode[i]});
357                 break;
358             case Opcodes.NEW:
359                 ins = new CPInstruction(new byte[] { byteCode[i],
360                                                      byteCode[i+1],
361                                                      byteCode[i+2] }, cp);
362                 iMod = 2;//i += 2;
363
break;
364             case Opcodes.NEWARRAY:
365                 ins = new Instruction(new byte[] { byteCode[i],
366                                                    byteCode[i+1] });
367                 iMod = 1; //i += 1;
368
break;
369             case Opcodes.ANEWARRAY:
370                 ins = new CPInstruction(new byte[] { byteCode[i],
371                                                      byteCode[i+1],
372                                                      byteCode[i+2] }, cp);
373                 iMod = 2;//i += 2;
374
break;
375             case Opcodes.ARRAYLENGTH:
376                 ins = new Instruction(new byte[] { byteCode[i] } );
377                 break;
378             case Opcodes.ATHROW:
379                 ins = new Instruction(new byte[] { byteCode[i] } );
380                 break;
381             case Opcodes.CHECKCAST:
382                 ins = new CPInstruction(new byte[] { byteCode[i],
383                                                      byteCode[i+1],
384                                                      byteCode[i+2] }, cp);
385                 iMod = 2;//i += 2;
386
break;
387             case Opcodes.INSTANCEOF:
388                 ins = new CPInstruction(new byte[] { byteCode[i],
389                                                      byteCode[i+1],
390                                                      byteCode[i+2] }, cp);
391                 iMod = 2;//i += 2;
392
break;
393             case Opcodes.MONITORENTER:
394             case Opcodes.MONITOREXIT:
395                 ins = new Instruction(new byte[] { byteCode[i] });
396                 break;
397             case Opcodes.WIDE:
398                 if (byteCode[i + 1] == Opcodes.IINC) {
399                     // Format 2:
400
ins = new Instruction(new byte[] { byteCode[i],
401                                                        byteCode[i+1],
402                                                        byteCode[i+2],
403                                                        byteCode[i+3],
404                                                        byteCode[i+4],
405                                                        byteCode[i+5] });
406                     iMod = 5;//i += 5;
407
}
408                 else {
409                     // Format 1:
410
ins = new Instruction(new byte[] { byteCode[i],
411                                                        byteCode[i+1],
412                                                        byteCode[i+2],
413                                                        byteCode[i+3] });
414                     iMod = 3;//i += 3;
415
}
416                 break;
417             case Opcodes.MULTIANEWARRAY:
418                 byte dim = byteCode[i+4];
419                 ins = new Instruction(new byte[] { byteCode[i],
420                                                    byteCode[i+1],
421                                                    byteCode[i+2],
422                                                    byteCode[i+3],
423                                                    dim }/*, dim*/);
424                 iMod = 4;//i += 4;
425
break;
426             case Opcodes.IFNULL:
427             case Opcodes.IFNONNULL:
428                 branchesFound = true;
429                 ins = new BranchInstruction(new byte[] { byteCode[i],
430                                                          byteCode[i+1],
431                                                          byteCode[i+2] });
432                 iMod = 2;//i += 2;
433
break;
434             case Opcodes.GOTO_W:
435                 branchesFound = true;
436                 ins = new BranchInstruction(new byte[] { byteCode[i],
437                                                          byteCode[i+1],
438                                                          byteCode[i+2],
439                                                          byteCode[i+3],
440                                                          byteCode[i+4] });
441                 iMod = 4;//i += 4;
442
break;
443             case Opcodes.JSR_W:
444                 branchesFound = true;
445                 ins = new BranchInstruction(new byte[] { byteCode[i],
446                                                          byteCode[i+1],
447                                                          byteCode[i+2],
448                                                          byteCode[i+3],
449                                                          byteCode[i+4] });
450                 iMod = 4;//i += 4;
451
break;
452             case Opcodes.BREAKPOINT:
453             case Opcodes.IMPDEP1:
454             case Opcodes.IMPDEP2:
455                 ins = new Instruction(new byte[] { byteCode[i] });
456                 break;
457             }
458
459             ins.setOffset((short)i);
460             i += iMod;
461
462             list.add(ins);
463         }
464
465         // Now we have created raw Instructions.
466
// If we have created any instruction in branch family,
467
// resolve their target instructions.
468
if (branchesFound) {
469             // find branch targets
470
for (int i = 0; i < list.size(); i++) {
471                 Instruction ins = (Instruction)list.get(i);
472                 if (ins instanceof BranchInstruction) {
473                     // Simple branch
474

475                     BranchInstruction bi = (BranchInstruction)ins;
476                     int offset = bi.getTargetOffset();
477
478                     Instruction target = null;
479                     //target = findTarget(list, i, offset);
480
//target = findTarget(list, 0, (bi.getOffset() + offset));
481
target = findTarget(list, (bi.getOffset() + offset));
482             if (target != null) {
483             bi.setTarget(target);
484             }
485             else {
486             System.out.println("Error locating branch target for instruction at " + i + ": " + bi);
487             }
488                 }
489                 else if (ins instanceof SwitchInstruction) {
490                     // complex branch
491

492                     SwitchInstruction si = (SwitchInstruction)ins;
493                     int dOffset = si.getDefaultOffset();
494
495                     // default target:
496
Instruction target = null;
497                     target = findTarget(list, i, dOffset);
498                     si.setDefault(target);
499
500                     // targets:
501
int[] tOffsets = si.getTargetOffsets();
502
503                     Instruction[] targets = new Instruction[tOffsets.length];
504                     for (int j = 0; j < targets.length; j++) {
505                         targets[j] = findTarget(list, i, tOffsets[j]);
506                     }
507                     si.setTargets(targets);
508                 }
509             }
510         }
511
512
513         return list;
514     }
515
516     /**
517      * Finds a jump target
518      */

519     private Instruction findTarget(List JavaDoc list, int offset) {
520         int idx = 0;
521         int currentOffset = 0;
522         while (currentOffset != offset) {
523         if (idx == list.size()) {
524         return null;
525         }
526
527             Instruction ins = (Instruction)list.get(idx);
528             currentOffset += ins.length();
529             idx++;
530         }
531
532         return (Instruction)list.get(idx);
533     }
534
535     /**
536      * Finds a jump target
537      */

538     private Instruction findTarget(List JavaDoc list, int idx, int offset) {
539         int offs = offset;
540         int dir = 1;
541         if (offset < 0) {
542             offs = -offset;
543             dir = -1;
544         }
545
546         int i = 0;
547
548         while(i < offs) {
549             Instruction ins = (Instruction)list.get(idx);
550             i += ins.length();
551             idx += dir;
552         }
553
554         // Replace 'target' instruction with TargetInstruction
555
Instruction target = (Instruction)list.get(idx);
556         TargetInstruction ti = new TargetInstruction(target);
557         list.set(idx, ti);
558
559         return ti;
560     }
561 }
562
Popular Tags