src/share/classes/com/sun/tools/javap/CodeWriter.java

changeset 46
7708bd6d800d
child 54
eaf608c64fec
equal deleted inserted replaced
42:f7e64b33d5a4 46:7708bd6d800d
1 /*
2 * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26 package com.sun.tools.javap;
27
28 import com.sun.tools.classfile.AccessFlags;
29 import com.sun.tools.classfile.Code_attribute;
30 import com.sun.tools.classfile.ConstantPool;
31 import com.sun.tools.classfile.ConstantPoolException;
32 import com.sun.tools.classfile.DescriptorException;
33 import com.sun.tools.classfile.Method;
34
35 import static com.sun.tools.classfile.OpCodes.*;
36
37 /*
38 * Write the contents of a Code attribute.
39 *
40 * <p><b>This is NOT part of any API supported by Sun Microsystems. If
41 * you write code that depends on this, you do so at your own risk.
42 * This code and its internal interfaces are subject to change or
43 * deletion without notice.</b>
44 */
45 class CodeWriter extends BasicWriter {
46 static CodeWriter instance(Context context) {
47 CodeWriter instance = context.get(CodeWriter.class);
48 if (instance == null)
49 instance = new CodeWriter(context);
50 return instance;
51 }
52
53 protected CodeWriter(Context context) {
54 super(context);
55 context.put(CodeWriter.class, this);
56 attrWriter = AttributeWriter.instance(context);
57 classWriter = ClassWriter.instance(context);
58 constantWriter = ConstantWriter.instance(context);
59 }
60
61 void write(Code_attribute attr, ConstantPool constant_pool) {
62 println(" Code:");
63 writeVerboseHeader(attr, constant_pool);
64 writeInstrs(attr);
65 writeExceptionTable(attr);
66 attrWriter.write(attr, attr.attributes, constant_pool);
67 }
68
69 public void writeVerboseHeader(Code_attribute attr, ConstantPool constant_pool) {
70 Method method = classWriter.getMethod();
71 String argCount;
72 try {
73 int n = method.descriptor.getParameterCount(constant_pool);
74 if (!method.access_flags.is(AccessFlags.ACC_STATIC))
75 ++n; // for 'this'
76 argCount = Integer.toString(n);
77 } catch (ConstantPoolException e) {
78 argCount = report(e);
79 } catch (DescriptorException e) {
80 argCount = report(e);
81 }
82
83 println(" Stack=" + attr.max_stack +
84 ", Locals=" + attr.max_locals +
85 ", Args_size=" + argCount);
86
87 }
88
89 public void writeInstrs(Code_attribute attr) {
90 try {
91 for (int pc = 0; pc < attr.code_length;) {
92 print(" " + pc + ":\t");
93 pc += writeInstr(attr, pc);
94 println();
95 }
96 } catch (Code_attribute.InvalidIndex e) {
97 println(report(e));
98 }
99 }
100
101 public int writeInstr(Code_attribute attr, int pc)
102 throws Code_attribute.InvalidIndex {
103 String lP = "";
104 int opcode = attr.getUnsignedByte(pc);
105 int opcode2;
106 String mnem;
107 switch (opcode) {
108 case opc_nonpriv:
109 case opc_priv: {
110 opcode2 = attr.getUnsignedByte(pc + 1);
111 mnem = opcName((opcode << 8) + opcode2);
112 if (mnem == null) {
113 mnem = opcName(opcode) + " " + opcode2;
114 }
115 print(mnem);
116 return 2;
117 }
118 case opc_wide: {
119 opcode2 = attr.getUnsignedByte(pc + 1);
120 mnem = opcName((opcode << 8) + opcode2);
121 if (mnem == null) {
122 print("bytecode " + opcode);
123 return 1;
124 }
125 print(mnem + " " + attr.getUnsignedShort(pc + 2));
126 if (opcode2 == opc_iinc) {
127 print(", " + attr.getShort(pc + 4));
128 return 6;
129 }
130 return 4;
131 }
132 }
133 mnem = opcName(opcode);
134 if (mnem == null) {
135 print("bytecode " + opcode);
136 return 1;
137 }
138 if (opcode > opc_jsr_w) {
139 print("bytecode " + opcode);
140 return 1;
141 }
142 print(opcName(opcode));
143 switch (opcode) {
144 case opc_aload:
145 case opc_astore:
146 case opc_fload:
147 case opc_fstore:
148 case opc_iload:
149 case opc_istore:
150 case opc_lload:
151 case opc_lstore:
152 case opc_dload:
153 case opc_dstore:
154 case opc_ret:
155 print("\t" + attr.getUnsignedByte(pc + 1));
156 return 2;
157 case opc_iinc:
158 print("\t" + attr.getUnsignedByte(pc + 1) + ", " + attr.getByte(pc + 2));
159 return 3;
160 case opc_tableswitch:
161 {
162 int tb = align(pc + 1);
163 int default_skip = attr.getInt(tb);
164 int low = attr.getInt(tb + 4);
165 int high = attr.getInt(tb + 8);
166 int count = high - low;
167 print("{ //" + low + " to " + high);
168 for (int i = 0; i <= count; i++) {
169 print("\n\t\t" + (i + low) + ": " + lP + (pc + attr.getInt(tb + 12 + 4 * i)) + ";");
170 }
171 print("\n\t\tdefault: " + lP + (default_skip + pc) + " }");
172 return tb - pc + 16 + count * 4;
173 }
174 case opc_lookupswitch:
175 {
176 int tb = align(pc + 1);
177 int default_skip = attr.getInt(tb);
178 int npairs = attr.getInt(tb + 4);
179 print("{ //" + npairs);
180 for (int i = 1; i <= npairs; i++) {
181 print("\n\t\t" + attr.getInt(tb + i * 8) + ": " + lP + (pc + attr.getInt(tb + 4 + i * 8)) + ";");
182 }
183 print("\n\t\tdefault: " + lP + (default_skip + pc) + " }");
184 return tb - pc + (npairs + 1) * 8;
185 }
186 case opc_newarray:
187 int type = attr.getUnsignedByte(pc + 1);
188 switch (type) {
189 case T_BOOLEAN:
190 print(" boolean");
191 break;
192 case T_BYTE:
193 print(" byte");
194 break;
195 case T_CHAR:
196 print(" char");
197 break;
198 case T_SHORT:
199 print(" short");
200 break;
201 case T_INT:
202 print(" int");
203 break;
204 case T_LONG:
205 print(" long");
206 break;
207 case T_FLOAT:
208 print(" float");
209 break;
210 case T_DOUBLE:
211 print(" double");
212 break;
213 case T_CLASS:
214 print(" class");
215 break;
216 default:
217 print(" BOGUS TYPE:" + type);
218 }
219 return 2;
220 case opc_anewarray:
221 {
222 int index = attr.getUnsignedShort(pc + 1);
223 print("\t#" + index + "; //");
224 printConstant(index);
225 return 3;
226 }
227 case opc_sipush:
228 print("\t" + attr.getShort(pc + 1));
229 return 3;
230 case opc_bipush:
231 print("\t" + attr.getByte(pc + 1));
232 return 2;
233 case opc_ldc:
234 {
235 int index = attr.getUnsignedByte(pc + 1);
236 print("\t#" + index + "; //");
237 printConstant(index);
238 return 2;
239 }
240 case opc_ldc_w:
241 case opc_ldc2_w:
242 case opc_instanceof:
243 case opc_checkcast:
244 case opc_new:
245 case opc_putstatic:
246 case opc_getstatic:
247 case opc_putfield:
248 case opc_getfield:
249 case opc_invokevirtual:
250 case opc_invokespecial:
251 case opc_invokestatic:
252 {
253 int index = attr.getUnsignedShort(pc + 1);
254 print("\t#" + index + "; //");
255 printConstant(index);
256 return 3;
257 }
258 case opc_invokeinterface:
259 {
260 int index = attr.getUnsignedShort(pc + 1);
261 int nargs = attr.getUnsignedByte(pc + 3);
262 print("\t#" + index + ", " + nargs + "; //");
263 printConstant(index);
264 return 5;
265 }
266 case opc_multianewarray:
267 {
268 int index = attr.getUnsignedShort(pc + 1);
269 int dimensions = attr.getUnsignedByte(pc + 3);
270 print("\t#" + index + ", " + dimensions + "; //");
271 printConstant(index);
272 return 4;
273 }
274 case opc_jsr:
275 case opc_goto:
276 case opc_ifeq:
277 case opc_ifge:
278 case opc_ifgt:
279 case opc_ifle:
280 case opc_iflt:
281 case opc_ifne:
282 case opc_if_icmpeq:
283 case opc_if_icmpne:
284 case opc_if_icmpge:
285 case opc_if_icmpgt:
286 case opc_if_icmple:
287 case opc_if_icmplt:
288 case opc_if_acmpeq:
289 case opc_if_acmpne:
290 case opc_ifnull:
291 case opc_ifnonnull:
292 print("\t" + lP + (pc + attr.getShort(pc + 1)));
293 return 3;
294 case opc_jsr_w:
295 case opc_goto_w:
296 print("\t" + lP + (pc + attr.getInt(pc + 1)));
297 return 5;
298 default:
299 return 1;
300 }
301 }
302
303 public void writeExceptionTable(Code_attribute attr) {
304 if (attr.exception_table_langth > 0) {
305 println(" Exception table:");
306 println(" from to target type");
307 for (int i = 0; i < attr.exception_table.length; i++) {
308 Code_attribute.Exception_data handler = attr.exception_table[i];
309 printFixedWidthInt(handler.start_pc, 6);
310 printFixedWidthInt(handler.end_pc, 6);
311 printFixedWidthInt(handler.handler_pc, 6);
312 print(" ");
313 int catch_type = handler.catch_type;
314 if (catch_type == 0) {
315 println("any");
316 } else {
317 print("Class ");
318 println(constantWriter.stringValue(catch_type));
319 println("");
320 }
321 }
322 }
323
324 }
325
326 private void printConstant(int index) {
327 constantWriter.write(index);
328 }
329
330 private void printFixedWidthInt(int n, int width) {
331 String s = String.valueOf(n);
332 for (int i = s.length(); i < width; i++)
333 print(" ");
334 print(s);
335 }
336
337 private static int align(int n) {
338 return (n + 3) & ~3;
339 }
340
341 private AttributeWriter attrWriter;
342 private ClassWriter classWriter;
343 private ConstantWriter constantWriter;
344 }

mercurial