KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jarg > OpecodeCounter


1 /* ====================================================================
2  * Copyright (c) 2002, Hidetoshi Ohuchi <hchacha@users.sourceforge.net>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *
12  * Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in the
14  * documentation and/or other materials provided with the distribution.
15  *
16  * Neither the name of the hchacha nor the names of its contributors
17  * may be used to endorse or promote products derived from this
18  * software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  * ====================================================================
33  */

34 package jarg;
35
36 import java.io.IOException JavaDoc;
37
38 import org.apache.bcel.classfile.*;
39 import org.apache.bcel.generic.*;
40 import org.apache.bcel.Constants;
41 import org.apache.bcel.util.*;
42
43 /**
44  * The class for counting opecode of byte-code.
45  *
46  * @version $Id: OpecodeCounter.java,v 1.1 2002/05/01 19:04:33 hchacha Exp $
47  * @author Hidetoshi Ohuchi &lt;hchacha@users.sourceforge.net&gt;
48  */

49 class OpecodeCounter {
50    static int countOpcode(byte[] code) {
51       int count = 0;
52       boolean wide = false;
53       ByteSequence stream = new ByteSequence(code);
54
55       try {
56          for (int i=0; stream.available() > 0; count++) {
57             wide = fetchOpcode(stream, wide);
58          }
59       } catch(IOException JavaDoc ex) {
60          ex.printStackTrace();
61          throw new ClassFormatError JavaDoc("Byte code error: " + ex);
62       }
63
64       return count;
65    }
66
67    private static final boolean fetchOpcode(ByteSequence bytes, boolean wide) throws IOException JavaDoc {
68       short opcode = (short)bytes.readUnsignedByte();
69       int default_offset=0, low, high, npairs;
70       int index, vindex, constant;
71       int[] match, jump_table;
72       int no_pad_bytes=0, offset;
73
74       // Special case: Skip (0-3) padding bytes, i.e., the
75
// following bytes are 4-byte-aligned
76
if ((opcode == Constants.TABLESWITCH) || (opcode == Constants.LOOKUPSWITCH)) {
77          int remainder = bytes.getIndex() % 4;
78          no_pad_bytes = (remainder == 0) ? 0 : 4 - remainder;
79
80          for (int i=0; i < no_pad_bytes; i++) {
81             byte b = bytes.readByte();
82             if (b != 0) {
83                System.err.println("Warning: Padding byte != 0 in " +
84                                 Constants.OPCODE_NAMES[opcode] + ":" + b);
85             }
86          }
87
88          // Both cases have a field default_offset in common
89
default_offset = bytes.readInt();
90       }
91
92       switch(opcode) {
93       // Table switch has variable length arguments.
94
case Constants.TABLESWITCH:
95          low = bytes.readInt();
96          high = bytes.readInt();
97
98          for (int i=0; i < (high - low + 1); i++) {
99             bytes.readInt();
100          }
101          break;
102
103       // Lookup switch has variable length arguments.
104
case Constants.LOOKUPSWITCH: {
105          npairs = bytes.readInt();
106          offset = bytes.getIndex() - 8 - no_pad_bytes - 1;
107
108          for (int i=0; i < npairs; i++) {
109             bytes.readInt(); // match
110
bytes.readInt(); // jump
111
}
112       }
113          break;
114
115       // Two address bytes + offset from start of byte stream form the jump target
116
case Constants.GOTO: case Constants.IFEQ: case Constants.IFGE: case Constants.IFGT:
117       case Constants.IFLE: case Constants.IFLT: case Constants.JSR: case Constants.IFNE:
118       case Constants.IFNONNULL: case Constants.IFNULL: case Constants.IF_ACMPEQ:
119       case Constants.IF_ACMPNE: case Constants.IF_ICMPEQ: case Constants.IF_ICMPGE: case Constants.IF_ICMPGT:
120       case Constants.IF_ICMPLE: case Constants.IF_ICMPLT: case Constants.IF_ICMPNE:
121          bytes.readShort();
122          break;
123
124       // 32-bit wide jumps
125
case Constants.GOTO_W: case Constants.JSR_W:
126          bytes.readInt();
127          break;
128
129       // Index byte references local variable (register)
130
case Constants.ALOAD: case Constants.ASTORE: case Constants.DLOAD: case Constants.DSTORE: case Constants.FLOAD:
131       case Constants.FSTORE: case Constants.ILOAD: case Constants.ISTORE: case Constants.LLOAD: case Constants.LSTORE:
132       case Constants.RET:
133          if (wide) {
134             vindex = bytes.readUnsignedShort();
135             wide=false; // Clear flag
136
} else {
137             vindex = bytes.readUnsignedByte();
138          }
139          break;
140
141       /*
142        * Remember wide byte which is used to form a 16-bit address in the
143        * following instruction. Relies on that the method is called again with
144        * the following opcode.
145        */

146       case Constants.WIDE:
147          wide = true;
148          break;
149
150       // Array of basic type.
151
case Constants.NEWARRAY:
152          bytes.readByte();
153          break;
154
155       // Access object/class fields.
156
case Constants.GETFIELD: case Constants.GETSTATIC: case Constants.PUTFIELD: case Constants.PUTSTATIC:
157          index = bytes.readUnsignedShort();
158          break;
159
160       // Operands are references to classes in constant pool
161
case Constants.NEW:
162       case Constants.CHECKCAST:
163       case Constants.INSTANCEOF:
164          index = bytes.readUnsignedShort();
165          break;
166
167       // Operands are references to methods in constant pool
168
case Constants.INVOKESPECIAL: case Constants.INVOKESTATIC: case Constants.INVOKEVIRTUAL:
169          index = bytes.readUnsignedShort();
170          break;
171
172       case Constants.INVOKEINTERFACE:
173          index = bytes.readUnsignedShort();
174          int nargs = bytes.readUnsignedByte(); // historical, redundant
175
bytes.readUnsignedByte(); // Last byte is a reserved space
176
break;
177
178       // Operands are references to items in constant pool
179
case Constants.LDC_W: case Constants.LDC2_W:
180          index = bytes.readUnsignedShort();
181          break;
182
183       case Constants.LDC:
184          index = bytes.readUnsignedByte();
185          break;
186
187       // Array of references.
188
case Constants.ANEWARRAY:
189          index = bytes.readUnsignedShort();
190          break;
191
192       // Multidimensional array of references.
193
case Constants.MULTIANEWARRAY: {
194          index = bytes.readUnsignedShort();
195          int dimensions = bytes.readUnsignedByte();
196       }
197       break;
198
199       // Increment local variable.
200
case Constants.IINC:
201          if (wide) {
202            vindex = bytes.readUnsignedShort();
203            constant = bytes.readShort();
204            wide = false;
205          } else {
206            vindex = bytes.readUnsignedByte();
207            constant = bytes.readByte();
208          }
209          break;
210
211       default:
212          if (Constants.NO_OF_OPERANDS[opcode] > 0) {
213             for (int i=0; i < Constants.TYPE_OF_OPERANDS[opcode].length; i++) {
214                switch(Constants.TYPE_OF_OPERANDS[opcode][i]) {
215                case Constants.T_BYTE: bytes.readByte(); break;
216                case Constants.T_SHORT: bytes.readShort(); break;
217                case Constants.T_INT: bytes.readInt(); break;
218                default: // Never reached
219
System.err.println("Unreachable default case reached!");
220                   System.exit(-1);
221                }
222             }
223          }
224       }
225       return wide;
226    }
227 }
228
Popular Tags