Wed, 23 Sep 2009 19:15:04 -0700
6572945: javah should be written as an annotation processor, not a doclet
Reviewed-by: darcy
1 /*
2 * Copyright 2007-2008 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 */
26 package com.sun.tools.javap;
28 import java.util.ArrayList;
29 import java.util.List;
31 import com.sun.tools.classfile.AccessFlags;
32 import com.sun.tools.classfile.Code_attribute;
33 import com.sun.tools.classfile.ConstantPool;
34 import com.sun.tools.classfile.ConstantPoolException;
35 import com.sun.tools.classfile.DescriptorException;
36 import com.sun.tools.classfile.Instruction;
37 import com.sun.tools.classfile.Instruction.TypeKind;
38 import com.sun.tools.classfile.Method;
40 /*
41 * Write the contents of a Code attribute.
42 *
43 * <p><b>This is NOT part of any API supported by Sun Microsystems. If
44 * you write code that depends on this, you do so at your own risk.
45 * This code and its internal interfaces are subject to change or
46 * deletion without notice.</b>
47 */
48 class CodeWriter extends BasicWriter {
49 static CodeWriter instance(Context context) {
50 CodeWriter instance = context.get(CodeWriter.class);
51 if (instance == null)
52 instance = new CodeWriter(context);
53 return instance;
54 }
56 protected CodeWriter(Context context) {
57 super(context);
58 context.put(CodeWriter.class, this);
59 attrWriter = AttributeWriter.instance(context);
60 classWriter = ClassWriter.instance(context);
61 constantWriter = ConstantWriter.instance(context);
62 sourceWriter = SourceWriter.instance(context);
63 tryBlockWriter = TryBlockWriter.instance(context);
64 stackMapWriter = StackMapWriter.instance(context);
65 localVariableTableWriter = LocalVariableTableWriter.instance(context);
66 localVariableTypeTableWriter = LocalVariableTypeTableWriter.instance(context);
67 typeAnnotationWriter = TypeAnnotationWriter.instance(context);
68 options = Options.instance(context);
69 }
71 void write(Code_attribute attr, ConstantPool constant_pool) {
72 println("Code:");
73 indent(+1);
74 writeVerboseHeader(attr, constant_pool);
75 writeInstrs(attr);
76 writeExceptionTable(attr);
77 attrWriter.write(attr, attr.attributes, constant_pool);
78 indent(-1);
79 }
81 public void writeVerboseHeader(Code_attribute attr, ConstantPool constant_pool) {
82 Method method = classWriter.getMethod();
83 String argCount;
84 try {
85 int n = method.descriptor.getParameterCount(constant_pool);
86 if (!method.access_flags.is(AccessFlags.ACC_STATIC))
87 ++n; // for 'this'
88 argCount = Integer.toString(n);
89 } catch (ConstantPoolException e) {
90 argCount = report(e);
91 } catch (DescriptorException e) {
92 argCount = report(e);
93 }
95 println("stack=" + attr.max_stack +
96 ", locals=" + attr.max_locals +
97 ", args_size=" + argCount);
99 }
101 public void writeInstrs(Code_attribute attr) {
102 List<InstructionDetailWriter> detailWriters = getDetailWriters(attr);
104 for (Instruction instr: attr.getInstructions()) {
105 try {
106 for (InstructionDetailWriter w: detailWriters)
107 w.writeDetails(instr);
108 writeInstr(instr);
109 } catch (ArrayIndexOutOfBoundsException e) {
110 println(report("error at or after byte " + instr.getPC()));
111 break;
112 }
113 }
115 for (InstructionDetailWriter w: detailWriters)
116 w.flush();
117 }
119 public void writeInstr(Instruction instr) {
120 print(String.format("%4d: %-13s ", instr.getPC(), instr.getMnemonic()));
121 instr.accept(instructionPrinter, null);
122 println();
123 }
124 // where
125 Instruction.KindVisitor<Void,Void> instructionPrinter =
126 new Instruction.KindVisitor<Void,Void>() {
128 public Void visitNoOperands(Instruction instr, Void p) {
129 return null;
130 }
132 public Void visitArrayType(Instruction instr, TypeKind kind, Void p) {
133 print(" " + kind.name);
134 return null;
135 }
137 public Void visitBranch(Instruction instr, int offset, Void p) {
138 print((instr.getPC() + offset));
139 return null;
140 }
142 public Void visitConstantPoolRef(Instruction instr, int index, Void p) {
143 print("#" + index);
144 tab();
145 print("// ");
146 printConstant(index);
147 return null;
148 }
150 public Void visitConstantPoolRefAndValue(Instruction instr, int index, int value, Void p) {
151 print("#" + index + ", " + value);
152 tab();
153 print("// ");
154 printConstant(index);
155 return null;
156 }
158 public Void visitLocal(Instruction instr, int index, Void p) {
159 print(index);
160 return null;
161 }
163 public Void visitLocalAndValue(Instruction instr, int index, int value, Void p) {
164 print(index + ", " + value);
165 return null;
166 }
168 public Void visitLookupSwitch(Instruction instr, int default_, int npairs, int[] matches, int[] offsets) {
169 int pc = instr.getPC();
170 print("{ // " + npairs);
171 indent(+1);
172 for (int i = 0; i < npairs; i++) {
173 print("\n" + matches[i] + ": " + (pc + offsets[i]));
174 }
175 print("\ndefault: " + (pc + default_) + " }");
176 indent(-1);
177 return null;
178 }
180 public Void visitTableSwitch(Instruction instr, int default_, int low, int high, int[] offsets) {
181 int pc = instr.getPC();
182 print("{ //" + low + " to " + high);
183 indent(+1);
184 for (int i = 0; i < offsets.length; i++) {
185 print("\n" + (low + i) + ": " + (pc + offsets[i]));
186 }
187 print("\ndefault: " + (pc + default_) + " }");
188 indent(-1);
189 return null;
190 }
192 public Void visitValue(Instruction instr, int value, Void p) {
193 print(value);
194 return null;
195 }
197 public Void visitUnknown(Instruction instr, Void p) {
198 return null;
199 }
200 };
203 public void writeExceptionTable(Code_attribute attr) {
204 if (attr.exception_table_langth > 0) {
205 println("Exception table:");
206 indent(+1);
207 println(" from to target type");
208 for (int i = 0; i < attr.exception_table.length; i++) {
209 Code_attribute.Exception_data handler = attr.exception_table[i];
210 print(String.format(" %5d %5d %5d",
211 handler.start_pc, handler.end_pc, handler.handler_pc));
212 print(" ");
213 int catch_type = handler.catch_type;
214 if (catch_type == 0) {
215 println("any");
216 } else {
217 print("Class ");
218 println(constantWriter.stringValue(catch_type));
219 }
220 }
221 indent(-1);
222 }
224 }
226 private void printConstant(int index) {
227 constantWriter.write(index);
228 }
230 private List<InstructionDetailWriter> getDetailWriters(Code_attribute attr) {
231 List<InstructionDetailWriter> detailWriters =
232 new ArrayList<InstructionDetailWriter>();
233 if (options.details.contains(InstructionDetailWriter.Kind.SOURCE)) {
234 sourceWriter.reset(classWriter.getClassFile(), attr);
235 detailWriters.add(sourceWriter);
236 }
238 if (options.details.contains(InstructionDetailWriter.Kind.LOCAL_VARS)) {
239 localVariableTableWriter.reset(attr);
240 detailWriters.add(localVariableTableWriter);
241 }
243 if (options.details.contains(InstructionDetailWriter.Kind.LOCAL_VAR_TYPES)) {
244 localVariableTypeTableWriter.reset(attr);
245 detailWriters.add(localVariableTypeTableWriter);
246 }
248 if (options.details.contains(InstructionDetailWriter.Kind.STACKMAPS)) {
249 stackMapWriter.reset(attr);
250 stackMapWriter.writeInitialDetails();
251 detailWriters.add(stackMapWriter);
252 }
254 if (options.details.contains(InstructionDetailWriter.Kind.TRY_BLOCKS)) {
255 tryBlockWriter.reset(attr);
256 detailWriters.add(tryBlockWriter);
257 }
259 if (options.details.contains(InstructionDetailWriter.Kind.TYPE_ANNOS)) {
260 typeAnnotationWriter.reset(attr);
261 detailWriters.add(typeAnnotationWriter);
262 }
264 return detailWriters;
265 }
267 private AttributeWriter attrWriter;
268 private ClassWriter classWriter;
269 private ConstantWriter constantWriter;
270 private LocalVariableTableWriter localVariableTableWriter;
271 private LocalVariableTypeTableWriter localVariableTypeTableWriter;
272 private TypeAnnotationWriter typeAnnotationWriter;
273 private SourceWriter sourceWriter;
274 private StackMapWriter stackMapWriter;
275 private TryBlockWriter tryBlockWriter;
276 private Options options;
277 }