KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > edu > umd > cs > findbugs > visitclass > DismantleBytecode


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

19
20 package edu.umd.cs.findbugs.visitclass;
21
22 import java.io.ByteArrayInputStream JavaDoc;
23 import java.io.DataInputStream JavaDoc;
24 import java.io.IOException JavaDoc;
25 import java.text.NumberFormat JavaDoc;
26 import java.util.HashMap JavaDoc;
27
28 import org.apache.bcel.classfile.Code;
29 import org.apache.bcel.classfile.CodeException;
30 import org.apache.bcel.classfile.Constant;
31 import org.apache.bcel.classfile.ConstantCP;
32 import org.apache.bcel.classfile.ConstantClass;
33 import org.apache.bcel.classfile.ConstantDouble;
34 import org.apache.bcel.classfile.ConstantFieldref;
35 import org.apache.bcel.classfile.ConstantFloat;
36 import org.apache.bcel.classfile.ConstantInteger;
37 import org.apache.bcel.classfile.ConstantInterfaceMethodref;
38 import org.apache.bcel.classfile.ConstantLong;
39 import org.apache.bcel.classfile.ConstantMethodref;
40 import org.apache.bcel.classfile.ConstantNameAndType;
41 import org.apache.bcel.classfile.ConstantString;
42 import org.apache.bcel.classfile.LineNumberTable;
43
44 import edu.umd.cs.findbugs.annotations.SuppressWarnings;
45
46 abstract public class DismantleBytecode extends AnnotationVisitor {
47
48     private int opcode;
49     private boolean opcodeIsWide;
50     private int PC,nextPC;
51     private int branchOffset;
52     private int branchTarget;
53     private int branchFallThrough;
54     private int[] switchOffsets;
55     private int[] switchLabels;
56     private int[] prevOpcode = new int[32];
57     private int currentPosInPrevOpcodeBuffer;
58     private int sizePrevOpcodeBuffer;
59     private int defaultSwitchOffset;
60     private String JavaDoc classConstantOperand;
61     private String JavaDoc dottedClassConstantOperand;
62     private String JavaDoc nameConstantOperand;
63     private String JavaDoc sigConstantOperand;
64     private String JavaDoc dottedSigConstantOperand;
65     private String JavaDoc stringConstantOperand;
66     private String JavaDoc refConstantOperand;
67     private boolean refFieldIsStatic;
68     private Constant constantRefOperand;
69     private int intConstant;
70     private long longConstant;
71     private float floatConstant;
72     private double doubleConstant;
73     private int registerOperand;
74     private boolean isRegisterLoad;
75     private boolean isRegisterStore;
76
77     private static final int INVALID_OFFSET = Integer.MIN_VALUE;
78     private static final String JavaDoc NOT_AVAILABLE = "none";
79
80     /*
81     protected static final int R_INT = 0;
82     protected static final int R_LONG = 1;
83     protected static final int R_FLOAT = 2;
84     protected static final int R_DOUBLE = 3;
85     protected static final int R_REF = 4;
86     protected int registerKind;
87     */

88
89     private static HashMap JavaDoc<String JavaDoc, String JavaDoc> replaceSlashesWithDotsCache = new HashMap JavaDoc<String JavaDoc, String JavaDoc>();
90
91     synchronized static String JavaDoc replaceSlashesWithDots(String JavaDoc c) {
92         String JavaDoc result = replaceSlashesWithDotsCache.get(c);
93         if (result != null) return result;
94         result = c.replace('/', '.');
95         replaceSlashesWithDotsCache.put(c, result);
96         return result;
97     }
98
99     /**
100      * Meaning of bytecode operands
101      */

102     public static final byte M_INT = 1;
103     public static final byte M_UINT = 2;
104     public static final byte M_CP = 3;
105     public static final byte M_R = 4;
106     public static final byte M_BR = 5;
107     public static final byte M_PAD = 6;
108     /**
109      * Meaning of bytecode operands
110      */

111     static final byte[][] MEANING_OF_OPERANDS = {
112         // 0 1 2 3 4 5 6 7 8 9
113
{}, {}, {}, {}, {}, {}, {}, {}, {}, {},
114         {}, {}, {}, {}, {}, {}, {M_INT}, {M_INT}, {M_CP}, {M_CP},
115         {M_CP}, {M_R}, {M_R}, {M_R}, {M_R}, {M_R}, {}, {}, {}, {},
116         {}, {}, {}, {}, {}, {}, {}, {}, {}, {},
117         {}, {}, {}, {}, {}, {}, {}, {}, {}, {},
118         {}, {}, {}, {}, {M_R}, {M_R}, {M_R}, {M_R}, {M_R}, {},
119         {}, {}, {}, {}, {}, {}, {}, {}, {}, {},
120         {}, {}, {}, {}, {}, {}, {}, {}, {}, {},
121         {}, {}, {}, {}, {}, {}, {}, {}, {}, {},
122         {}, {}, {}, {}, {}, {}, {}, {}, {}, {},
123         {}, {}, {}, {}, {}, {}, {}, {}, {}, {},
124         {}, {}, {}, {}, {}, {}, {}, {}, {}, {},
125         {}, {}, {}, {}, {}, {}, {}, {}, {}, {},
126 // 130 1 2 3 4 5 6 7 8 9
127
{}, {}, {M_R, M_INT}, {}, {}, {}, {}, {}, {}, {},
128         {}, {}, {}, {}, {}, {}, {}, {}, {}, {},
129         {}, {}, {}, {M_BR}, {M_BR}, {M_BR}, {M_BR}, {M_BR}, {M_BR}, {M_BR},
130         {M_BR}, {M_BR}, {M_BR}, {M_BR}, {M_BR}, {M_BR}, {M_BR}, {M_BR}, {M_BR}, {M_R},
131 // 170 1 2 3 4 5 6 7 8 9
132
{}, {}, {}, {}, {}, {}, {}, {}, {M_CP}, {M_CP},
133         {M_CP}, {M_CP}, {M_CP}, {M_CP}, {M_CP},
134         {M_CP, M_PAD, M_PAD}, {}, {M_CP}, {M_UINT}, {M_CP},
135 // 190 1 2 3 4 5 6 7 8 9
136
{}, {}, {M_CP}, {M_CP}, {}, {}, {M_PAD}, {M_CP, M_UINT}, {M_BR}, {M_BR},
137         {M_BR}, {M_BR}, {}, {}, {}, {}, {},
138         {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},
139         {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},
140         {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}
141     };
142
143
144     protected byte[] codeBytes;
145     protected LineNumberTable lineNumberTable;
146
147     // Accessors
148

149     /** If the current opcode has a class operand, get the associated class constant, dot-formatted */
150     public String JavaDoc getDottedClassConstantOperand() {
151         if (dottedClassConstantOperand == NOT_AVAILABLE)
152             throw new IllegalStateException JavaDoc("getDottedClassConstantOperand called but value not available");
153         return dottedClassConstantOperand;
154     }
155
156     /** If the current opcode has a reference constant operand, get its string representation */
157     public String JavaDoc getRefConstantOperand() {
158         if (refConstantOperand == NOT_AVAILABLE)
159             throw new IllegalStateException JavaDoc("getRefConstantOperand called but value not available");
160         if (refConstantOperand == null) {
161             StringBuffer JavaDoc ref = new StringBuffer JavaDoc(dottedClassConstantOperand.length() + nameConstantOperand.length() + dottedSigConstantOperand.length() + 5);
162         ref.append(dottedClassConstantOperand)
163             .append(".")
164             .append(nameConstantOperand)
165             .append(" : ")
166             .append(dottedSigConstantOperand);
167         refConstantOperand = ref.toString();
168         }
169         return refConstantOperand;
170     }
171
172     /** If the current opcode has a reference constant operand, get its name */
173     public String JavaDoc getNameConstantOperand() {
174         if (nameConstantOperand == NOT_AVAILABLE)
175             throw new IllegalStateException JavaDoc("getNameConstantOperand called but value not available");
176         return nameConstantOperand;
177     }
178
179     /** If the current opcode has a reference constant operand, get its signature, dot-formatted */
180     @Deprecated JavaDoc
181     public String JavaDoc getDottedSigConstantOperand() {
182         if (dottedSigConstantOperand == NOT_AVAILABLE)
183             throw new IllegalStateException JavaDoc("getDottedSigConstantOperand called but value not available");
184         return dottedSigConstantOperand;
185     }
186
187     /** If the current opcode has a reference constant operand, get its signature, slash-formatted */
188     public String JavaDoc getSigConstantOperand() {
189         if (sigConstantOperand == NOT_AVAILABLE)
190             throw new IllegalStateException JavaDoc("getSigConstantOperand called but value not available");
191         return sigConstantOperand;
192     }
193
194     public String JavaDoc getClassConstantOperand() {
195         if (classConstantOperand == NOT_AVAILABLE)
196             throw new IllegalStateException JavaDoc("getClassConstantOperand called but value not available");
197         return classConstantOperand;
198     }
199
200     /** If the current opcode has a string constant operand, get its name */
201     public String JavaDoc getStringConstantOperand() {
202         if (stringConstantOperand == NOT_AVAILABLE)
203             throw new IllegalStateException JavaDoc("getStringConstantOperand called but value not available");
204         return stringConstantOperand;
205     }
206
207     public Constant getConstantRefOperand() {
208         if (constantRefOperand == null)
209             throw new IllegalStateException JavaDoc("getConstantRefOperand called but value not available");
210         return constantRefOperand;
211     }
212
213     public boolean isRegisterLoad() {
214         return isRegisterLoad;
215         }
216     public boolean isRegisterStore() {
217         return isRegisterStore;
218         }
219
220     public int getRegisterOperand() {
221         if (registerOperand == -1)
222             throw new IllegalStateException JavaDoc("getRegisterOperand called but value not available");
223         return registerOperand;
224     }
225
226     public int getIntConstant() {
227         return intConstant;
228     }
229
230     public int getBranchOffset() {
231         if (branchOffset == INVALID_OFFSET)
232             throw new IllegalStateException JavaDoc("getBranchOffset called but value not available");
233         return branchOffset;
234     }
235
236     public int getBranchTarget() {
237         if (branchTarget == INVALID_OFFSET)
238             throw new IllegalStateException JavaDoc("getBranchTarget called but value not available");
239         return branchTarget;
240     }
241
242     public int getBranchFallThrough() {
243         if (branchFallThrough == INVALID_OFFSET)
244             throw new IllegalStateException JavaDoc("getBranchFallThrough called but value not available");
245         return branchFallThrough;
246     }
247
248     public int getDefaultSwitchOffset() {
249         if (defaultSwitchOffset == INVALID_OFFSET)
250             throw new IllegalStateException JavaDoc("getDefaultSwitchOffset called but value not available");
251         return defaultSwitchOffset;
252     }
253
254     public boolean getRefFieldIsStatic() {
255         return refFieldIsStatic;
256     }
257
258     public int getPC() {
259         return PC;
260     }
261
262     /**
263      * return previous opcode;
264      * @param offset 0 for current opcode, 1 for one before that, etc.
265      */

266     public int getPrevOpcode(int offset) {
267         if (offset >= prevOpcode.length || offset > sizePrevOpcodeBuffer)
268             return NOP;
269         int pos = currentPosInPrevOpcodeBuffer - offset;
270         if (pos < 0) pos += prevOpcode.length;
271         return prevOpcode[pos];
272     }
273     
274     /**
275      * Return whether or not given opcode is a branch instruction.
276      *
277      * @param opcode the opcode
278      * @return true if instruction is a branch, false if not
279      */

280     public static boolean isBranch(int opcode) {
281         byte[] operands = MEANING_OF_OPERANDS[opcode];
282         return operands.length > 0 && operands[0] == M_BR;
283     }
284     
285     /**
286      * Return whether or not given opcode is a switch instruction.
287      *
288      * @param opcode the opcode
289      * @return true if instruction is a switch, false if not
290      */

291     public static boolean isSwitch(int opcode) {
292         return opcode == LOOKUPSWITCH || opcode == TABLESWITCH;
293     }
294
295     @SuppressWarnings JavaDoc("EI")
296     public int[] getSwitchOffsets() {
297         if (switchOffsets == null)
298             throw new IllegalStateException JavaDoc("getSwitchOffsets called but value not available");
299         return switchOffsets;
300     }
301
302     @SuppressWarnings JavaDoc("EI")
303     public int[] getSwitchLabels() {
304         if (switchLabels == null)
305             throw new IllegalStateException JavaDoc("getSwitchOffsets called but value not available");
306         return switchLabels;
307     }
308
309     private void resetState() {
310         dottedClassConstantOperand = classConstantOperand = nameConstantOperand = sigConstantOperand = dottedSigConstantOperand = stringConstantOperand = refConstantOperand = NOT_AVAILABLE;
311         refFieldIsStatic = false;
312         constantRefOperand = null;
313         registerOperand = -1;
314         isRegisterLoad = false;
315         isRegisterStore = false;
316         branchOffset = branchTarget = branchFallThrough = defaultSwitchOffset = INVALID_OFFSET;
317         switchOffsets = switchLabels = null;
318     }
319
320     private static void sortByOffset(int[] switchOffsets, int[] switchLabels) {
321         int npairs = switchOffsets.length;
322         // Sort by offset
323
for (int j = 0; j < npairs; j++) {
324             int min = j;
325             for (int k = j + 1; k < npairs; k++)
326                 if (switchOffsets[min] > switchOffsets[k])
327                     min = k;
328             if (min > j) {
329                 int tmp = switchOffsets[min];
330                 switchOffsets[min] = switchOffsets[j];
331                 switchOffsets[j] = tmp;
332                 tmp = switchLabels[min];
333                 switchLabels[min] = switchLabels[j];
334                 switchLabels[j] = tmp;
335             }
336         }
337     }
338
339     public int getMaxPC() {
340         return codeBytes.length-1;
341         }
342     public int getCodeByte(int offset) {
343         return 0xff & codeBytes[offset];
344         }
345     public int getOpcode() {
346         return opcode;
347         }
348
349     public boolean atCatchBlock() {
350         for(CodeException e : getCode().getExceptionTable())
351             if (e.getHandlerPC() == getPC()) return true;
352         return false;
353     }
354     @Override JavaDoc
355     public void visit(Code obj) {
356         sizePrevOpcodeBuffer = 0;
357         currentPosInPrevOpcodeBuffer = prevOpcode.length-1;
358
359         int switchLow = 1000000;
360         int switchHigh = -1000000;
361         codeBytes = obj.getCode();
362         DataInputStream JavaDoc byteStream = new DataInputStream JavaDoc(new ByteArrayInputStream JavaDoc(codeBytes));
363
364         lineNumberTable = obj.getLineNumberTable();
365
366         try {
367             for (int i = 0; i < codeBytes.length;) {
368                 resetState();
369                 PC = i;
370                 opcodeIsWide = false;
371                 opcode = byteStream.readUnsignedByte();
372                 sizePrevOpcodeBuffer++;
373                 currentPosInPrevOpcodeBuffer++;
374                 if (currentPosInPrevOpcodeBuffer >= prevOpcode.length)
375                     currentPosInPrevOpcodeBuffer = 0;
376                 prevOpcode[currentPosInPrevOpcodeBuffer] = opcode;
377                 i++;
378                 // System.out.println(OPCODE_NAMES[opCode]);
379
int byteStreamArgCount = NO_OF_OPERANDS[opcode];
380                 if (byteStreamArgCount == UNPREDICTABLE) {
381
382                     if (opcode == LOOKUPSWITCH) {
383                         int pad = 4 - (i & 3);
384                         if (pad == 4) pad = 0;
385                         int count = pad;
386                         while (count > 0)
387                             count -= byteStream.skipBytes(count);
388                         i += pad;
389                         defaultSwitchOffset = byteStream.readInt();
390                         branchOffset = defaultSwitchOffset;
391                         branchTarget = branchOffset + PC;
392                         i += 4;
393                         int npairs = byteStream.readInt();
394                         i += 4;
395                         switchOffsets = new int[npairs];
396                         switchLabels = new int[npairs];
397                         for (int o = 0; o < npairs; o++) {
398                             switchLabels[o] = byteStream.readInt();
399                             switchOffsets[o] = byteStream.readInt();
400                             i += 8;
401                         }
402                         sortByOffset(switchOffsets, switchLabels);
403                     } else if (opcode == TABLESWITCH) {
404                         int pad = 4 - (i & 3);
405                         if (pad == 4) pad = 0;
406                         int count = pad;
407                         while (count > 0)
408                             count -= byteStream.skipBytes(count);
409                         i += pad;
410                         defaultSwitchOffset = byteStream.readInt();
411                         branchOffset = defaultSwitchOffset;
412                         branchTarget = branchOffset + PC;
413                         i += 4;
414                         switchLow = byteStream.readInt();
415                         i += 4;
416                         switchHigh = byteStream.readInt();
417                         i += 4;
418                         int npairs = switchHigh - switchLow + 1;
419                         switchOffsets = new int[npairs];
420                         switchLabels = new int[npairs];
421                         for (int o = 0; o < npairs; o++) {
422                             switchLabels[o] = o + switchLow;
423                             switchOffsets[o] = byteStream.readInt();
424                             i += 4;
425                         }
426                         sortByOffset(switchOffsets, switchLabels);
427                     } else if (opcode == WIDE) {
428                         opcodeIsWide = true;
429                         opcode = byteStream.readUnsignedByte();
430                         i++;
431                         switch (opcode) {
432                         case ILOAD:
433                         case FLOAD:
434                         case ALOAD:
435                         case LLOAD:
436                         case DLOAD:
437                         case ISTORE:
438                         case FSTORE:
439                         case ASTORE:
440                         case LSTORE:
441                         case DSTORE:
442                         case RET:
443                             registerOperand = byteStream.readUnsignedShort();
444                             i += 2;
445                             break;
446                         case IINC:
447                             registerOperand = byteStream.readUnsignedShort();
448                             i += 2;
449                             intConstant = byteStream.readShort();
450                             i += 2;
451                             break;
452                         default:
453                             throw new IllegalStateException JavaDoc("bad wide bytecode: " + OPCODE_NAMES[opcode]);
454                         }
455                     } else
456                         throw new IllegalStateException JavaDoc("bad unpredicatable bytecode: " + OPCODE_NAMES[opcode]);
457                 } else {
458                     if (byteStreamArgCount < 0) throw new IllegalStateException JavaDoc("bad length for bytecode: " + OPCODE_NAMES[opcode]);
459                     for (int k = 0; k < TYPE_OF_OPERANDS[opcode].length; k++) {
460
461                         int v;
462                         int t = TYPE_OF_OPERANDS[opcode][k];
463                         int m = MEANING_OF_OPERANDS[opcode][k];
464                         boolean unsigned = (m == M_CP || m == M_R || m == M_UINT);
465                         switch (t) {
466                         case T_BYTE:
467                             if (unsigned)
468                                 v = byteStream.readUnsignedByte();
469                             else
470                                 v = byteStream.readByte();
471                             /*
472                             System.out.print("Read byte " + v);
473                             System.out.println(" with meaning" + m);
474                             */

475                             i++;
476                             break;
477                         case T_SHORT:
478                             if (unsigned)
479                                 v = byteStream.readUnsignedShort();
480                             else
481                                 v = byteStream.readShort();
482                             i += 2;
483                             break;
484                         case T_INT:
485                             v = byteStream.readInt();
486                             i += 4;
487                             break;
488                         default:
489                             throw new IllegalStateException JavaDoc();
490                         }
491                         switch (m) {
492                         case M_BR:
493                             branchOffset = v;
494                             branchTarget = v + PC;
495                             branchFallThrough = i;
496                             break;
497                         case M_CP:
498                             constantRefOperand = getConstantPool().getConstant(v);
499                             if (constantRefOperand instanceof ConstantClass) {
500                                 ConstantClass clazz = (ConstantClass) constantRefOperand;
501                                 classConstantOperand = getStringFromIndex(clazz.getNameIndex());
502                                 dottedClassConstantOperand = replaceSlashesWithDots(classConstantOperand);
503                             }
504                             if (constantRefOperand instanceof ConstantInteger)
505                                 intConstant = ((ConstantInteger) constantRefOperand).getBytes();
506                             else if (constantRefOperand instanceof ConstantLong)
507                                 longConstant = ((ConstantLong) constantRefOperand).getBytes();
508                             else if (constantRefOperand instanceof ConstantFloat)
509                                 floatConstant = ((ConstantFloat) constantRefOperand).getBytes();
510                             else if (constantRefOperand instanceof ConstantDouble)
511                                 doubleConstant = ((ConstantDouble) constantRefOperand).getBytes();
512                             else if (constantRefOperand instanceof ConstantString) {
513                                 int s = ((ConstantString) constantRefOperand).getStringIndex();
514
515                                 stringConstantOperand = getStringFromIndex(s);
516                             } else if (constantRefOperand instanceof ConstantCP) {
517                                 ConstantCP cp = (ConstantCP) constantRefOperand;
518                                 ConstantClass clazz
519                                     = (ConstantClass) getConstantPool().getConstant(cp.getClassIndex());
520                                 classConstantOperand = getStringFromIndex(clazz.getNameIndex());
521                                 dottedClassConstantOperand = replaceSlashesWithDots(classConstantOperand);
522                                 ConstantNameAndType sig
523                                     = (ConstantNameAndType) getConstantPool().getConstant(cp.getNameAndTypeIndex());
524                                 nameConstantOperand = getStringFromIndex(sig.getNameIndex());
525                                 sigConstantOperand = getStringFromIndex(sig.getSignatureIndex());
526                                 dottedSigConstantOperand = replaceSlashesWithDots(sigConstantOperand);
527
528                                 refConstantOperand = null;
529                             }
530                             break;
531                         case M_R:
532                             registerOperand = v;
533                             break;
534                         case M_UINT:
535                         case M_INT:
536                             intConstant = v;
537                         }
538                     }
539
540                 }
541                 switch (opcode) {
542                 case IINC:
543                     isRegisterLoad = true;
544                     isRegisterStore = true;
545                     break;
546                 case ILOAD_0:
547                 case ILOAD_1:
548                 case ILOAD_2:
549                 case ILOAD_3:
550                     registerOperand = opcode - ILOAD_0;
551                     isRegisterLoad = true;
552                     break;
553
554                 case ALOAD_0:
555                 case ALOAD_1:
556                 case ALOAD_2:
557                 case ALOAD_3:
558                     registerOperand = opcode - ALOAD_0;
559                     isRegisterLoad = true;
560                     break;
561
562                 case FLOAD_0:
563                 case FLOAD_1:
564                 case FLOAD_2:
565                 case FLOAD_3:
566                     registerOperand = opcode - FLOAD_0;
567                     isRegisterLoad = true;
568                     break;
569
570                 case DLOAD_0:
571                 case DLOAD_1:
572                 case DLOAD_2:
573                 case DLOAD_3:
574                     registerOperand = opcode - DLOAD_0;
575                     isRegisterLoad = true;
576                     break;
577
578                 case LLOAD_0:
579                 case LLOAD_1:
580                 case LLOAD_2:
581                 case LLOAD_3:
582                     registerOperand = opcode - LLOAD_0;
583                     isRegisterLoad = true;
584                     break;
585                 case ILOAD:
586                 case FLOAD:
587                 case ALOAD:
588                 case LLOAD:
589                 case DLOAD:
590                     isRegisterLoad = true;
591                     break;
592
593
594
595
596                 case ISTORE_0:
597                 case ISTORE_1:
598                 case ISTORE_2:
599                 case ISTORE_3:
600                     registerOperand = opcode - ISTORE_0;
601                     isRegisterStore = true;
602                     break;
603
604                 case ASTORE_0:
605                 case ASTORE_1:
606                 case ASTORE_2:
607                 case ASTORE_3:
608                     registerOperand = opcode - ASTORE_0;
609                     isRegisterStore = true;
610                     break;
611
612                 case FSTORE_0:
613                 case FSTORE_1:
614                 case FSTORE_2:
615                 case FSTORE_3:
616                     registerOperand = opcode - FSTORE_0;
617                     isRegisterStore = true;
618                     break;
619
620                 case DSTORE_0:
621                 case DSTORE_1:
622                 case DSTORE_2:
623                 case DSTORE_3:
624                     registerOperand = opcode - DSTORE_0;
625                     isRegisterStore = true;
626                     break;
627
628                 case LSTORE_0:
629                 case LSTORE_1:
630                 case LSTORE_2:
631                 case LSTORE_3:
632                     registerOperand = opcode - LSTORE_0;
633                     isRegisterStore = true;
634                     break;
635                 case ISTORE:
636                 case FSTORE:
637                 case ASTORE:
638                 case LSTORE:
639                 case DSTORE:
640                     isRegisterStore = true;
641                     break;
642
643                 }
644
645
646                 switch (opcode) {
647                 case ILOAD:
648                 case FLOAD:
649                 case ALOAD:
650                 case LLOAD:
651                 case DLOAD:
652                     // registerKind = opcode - ILOAD;
653
break;
654                 case ISTORE:
655                 case FSTORE:
656                 case ASTORE:
657                 case LSTORE:
658                 case DSTORE:
659                     // registerKind = opcode - ISTORE;
660
break;
661                 case RET:
662                     // registerKind = R_REF;
663
break;
664                 case GETSTATIC:
665                 case PUTSTATIC:
666                     refFieldIsStatic = true;
667                     break;
668                 case GETFIELD:
669                 case PUTFIELD:
670                     refFieldIsStatic = false;
671                     break;
672                 }
673                 nextPC = i;
674                 sawOpcode(opcode);
675
676                 if (opcode == TABLESWITCH) {
677                     sawInt(switchLow);
678                     sawInt(switchHigh);
679                     int prevOffset = i - PC;
680                     for (int o = 0; o <= switchHigh - switchLow; o++) {
681                         sawBranchTo(switchOffsets[o] + PC);
682                         sawOffset(switchOffsets[o] - prevOffset);
683                         prevOffset = switchOffsets[o];
684                     }
685                     sawOffset(defaultSwitchOffset - prevOffset);
686                     sawBranchTo(defaultSwitchOffset + PC);
687                 } else if (opcode == LOOKUPSWITCH) {
688                     sawInt(switchOffsets.length);
689                     int prevOffset = i - PC;
690                     for (int o = 0; o < switchOffsets.length; o++) {
691                         sawBranchTo(switchOffsets[o] + PC);
692                         prevOffset = switchOffsets[o];
693                         sawInt(switchLabels[o]);
694                     }
695                     sawOffset(defaultSwitchOffset - prevOffset);
696                     sawBranchTo(defaultSwitchOffset + PC);
697                 } else
698                     for (int k = 0; k < TYPE_OF_OPERANDS[opcode].length; k++) {
699                         int m = MEANING_OF_OPERANDS[opcode][k];
700                         switch (m) {
701                         case M_BR:
702                             sawBranchTo(branchOffset + PC);
703                             if (branchOffset > 0)
704                                 sawOffset(branchOffset - (i - PC));
705                             else
706                                 sawOffset(branchOffset);
707                             break;
708                         case M_CP:
709                             if (constantRefOperand instanceof ConstantInteger)
710                                 sawInt(intConstant);
711                             else if (constantRefOperand instanceof ConstantLong)
712                                 sawLong(longConstant);
713                             else if (constantRefOperand instanceof ConstantFloat)
714                                 sawFloat(floatConstant);
715                             else if (constantRefOperand instanceof ConstantDouble)
716                                 sawDouble(doubleConstant);
717                             else if (constantRefOperand instanceof ConstantString)
718                                 sawString(stringConstantOperand);
719                             else if (constantRefOperand instanceof ConstantFieldref)
720                                 sawField();
721                             else if (constantRefOperand instanceof ConstantMethodref)
722                                 sawMethod();
723                             else if (constantRefOperand instanceof ConstantInterfaceMethodref)
724                                 sawIMethod();
725                             else if (constantRefOperand instanceof ConstantClass)
726                                 sawClass();
727                             break;
728                         case M_R:
729                             sawRegister(registerOperand);
730                             break;
731                         case M_INT:
732                             sawInt(intConstant);
733                             break;
734                         }
735                     }
736             }
737         } catch (IOException JavaDoc e) {
738             System.out.println("Got IO Exception:");
739             e.printStackTrace();
740         }
741
742         try {
743             byteStream.close();
744         } catch (IOException JavaDoc e) {
745             assert false;
746         }
747     }
748
749     public void sawDouble(double seen) {
750     }
751
752     public void sawFloat(float seen) {
753     }
754
755     public void sawRegister(int r) {
756     }
757
758     public void sawInt(int seen) {
759     }
760
761     public void sawLong(long seen) {
762     }
763
764     public void sawBranchTo(int seen) {
765     }
766     public void sawOffset(int seen) {
767     }
768
769     public void sawOpcode(int seen) {
770     }
771
772     public void sawString(String JavaDoc seen) {
773     }
774
775     public void sawField() {
776     }
777
778     public void sawMethod() {
779     }
780
781     public void sawIMethod() {
782     }
783
784     public void sawClass() {
785     }
786
787     static private NumberFormat JavaDoc formatter = NumberFormat.getIntegerInstance();
788     static {
789         formatter.setMinimumIntegerDigits(4);
790         formatter.setGroupingUsed(false);
791     }
792     public void printOpCode( int seen) {
793         System.out.print(" TestingGround: [" + formatter.format(getPC()) + "] " + OPCODE_NAMES[seen]);
794         if ((seen == INVOKEVIRTUAL) || (seen == INVOKESPECIAL) || (seen == INVOKEINTERFACE) || (seen == INVOKESTATIC))
795             System.out.print(" " + getClassConstantOperand() + "." + getNameConstantOperand() + " " + getSigConstantOperand());
796         else if (seen == LDC || seen == LDC_W || seen == LDC2_W) {
797             Constant c = getConstantRefOperand();
798             if (c instanceof ConstantString)
799                 System.out.print(" \"" + getStringConstantOperand() + "\"");
800             else if (c instanceof ConstantClass)
801                 System.out.print(" " + getClassConstantOperand());
802             else
803                 System.out.print(" " + c);
804         } else if ((seen == ALOAD) || (seen == ASTORE))
805             System.out.print(" " + getRegisterOperand());
806         else if ((seen == GOTO) || (seen == GOTO_W)
807         || (seen == IF_ACMPEQ) || (seen == IF_ACMPNE)
808         || (seen == IF_ICMPEQ) || (seen == IF_ICMPGE)
809         || (seen == IF_ICMPGT) || (seen == IF_ICMPLE)
810         || (seen == IF_ICMPLT) || (seen == IF_ICMPNE)
811         || (seen == IFEQ) || (seen == IFGE)
812         || (seen == IFGT) || (seen == IFLE)
813         || (seen == IFLT) || (seen == IFNE)
814         || (seen == IFNONNULL) || (seen == IFNULL))
815             System.out.print(" " + getBranchTarget());
816         else if ((seen == NEW) || (seen == INSTANCEOF))
817             System.out.print(" " + getClassConstantOperand());
818         else if ((seen == TABLESWITCH) || (seen == LOOKUPSWITCH)) {
819             System.out.print(" [");
820             int switchPC = getPC();
821             int[] offsets = getSwitchOffsets();
822             for (int offset : offsets) {
823                 System.out.print((switchPC + offset) + ",");
824             }
825             System.out.print((switchPC + getDefaultSwitchOffset()) + "]");
826         }
827     
828         System.out.println();
829     }
830
831
832     /**
833      * @return Returns the nextPC.
834      */

835     public int getNextPC() {
836         return nextPC;
837     }
838 }
839
Popular Tags