Thu, 30 Jul 2009 09:18:55 -0700
4880672: javap does not output inner interfaces of an interface
Reviewed-by: mcimadamore
1 /*
2 * Copyright 2009 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 com.sun.tools.classfile.AccessFlags;
29 import java.util.HashMap;
30 import java.util.Map;
32 import com.sun.tools.classfile.Attribute;
33 import com.sun.tools.classfile.Code_attribute;
34 import com.sun.tools.classfile.ConstantPool;
35 import com.sun.tools.classfile.ConstantPoolException;
36 import com.sun.tools.classfile.Descriptor;
37 import com.sun.tools.classfile.Descriptor.InvalidDescriptor;
38 import com.sun.tools.classfile.Instruction;
39 import com.sun.tools.classfile.Method;
40 import com.sun.tools.classfile.StackMapTable_attribute;
41 import com.sun.tools.classfile.StackMapTable_attribute.*;
43 import static com.sun.tools.classfile.StackMapTable_attribute.verification_type_info.*;
45 /**
46 * Annotate instructions with stack map.
47 *
48 * <p><b>This is NOT part of any API supported by Sun Microsystems. If
49 * you write code that depends on this, you do so at your own risk.
50 * This code and its internal interfaces are subject to change or
51 * deletion without notice.</b>
52 */
53 public class StackMapWriter extends InstructionDetailWriter {
54 static StackMapWriter instance(Context context) {
55 StackMapWriter instance = context.get(StackMapWriter.class);
56 if (instance == null)
57 instance = new StackMapWriter(context);
58 return instance;
59 }
61 protected StackMapWriter(Context context) {
62 super(context);
63 context.put(StackMapWriter.class, this);
64 classWriter = ClassWriter.instance(context);
65 }
67 public void reset(Code_attribute attr) {
68 setStackMap((StackMapTable_attribute) attr.attributes.get(Attribute.StackMapTable));
69 }
71 void setStackMap(StackMapTable_attribute attr) {
72 if (attr == null) {
73 map = null;
74 return;
75 }
77 Method m = classWriter.getMethod();
78 Descriptor d = m.descriptor;
79 String[] args;
80 try {
81 ConstantPool cp = classWriter.getClassFile().constant_pool;
82 String argString = d.getParameterTypes(cp);
83 args = argString.substring(1, argString.length() - 1).split("[, ]+");
84 } catch (ConstantPoolException e) {
85 return;
86 } catch (InvalidDescriptor e) {
87 return;
88 }
89 boolean isStatic = m.access_flags.is(AccessFlags.ACC_STATIC);
91 verification_type_info[] initialLocals = new verification_type_info[(isStatic ? 0 : 1) + args.length];
92 if (!isStatic)
93 initialLocals[0] = new CustomVerificationTypeInfo("this");
94 for (int i = 0; i < args.length; i++) {
95 initialLocals[(isStatic ? 0 : 1) + i] =
96 new CustomVerificationTypeInfo(args[i].replace(".", "/"));
97 }
99 map = new HashMap<Integer, StackMap>();
100 StackMapBuilder builder = new StackMapBuilder();
102 // using -1 as the pc for the initial frame effectively compensates for
103 // the difference in behavior for the first stack map frame (where the
104 // pc offset is just offset_delta) compared to subsequent frames (where
105 // the pc offset is always offset_delta+1).
106 int pc = -1;
108 map.put(pc, new StackMap(initialLocals, empty));
110 for (int i = 0; i < attr.entries.length; i++)
111 pc = attr.entries[i].accept(builder, pc);
112 }
114 public void writeInitialDetails() {
115 writeDetails(-1);
116 }
118 public void writeDetails(Instruction instr) {
119 writeDetails(instr.getPC());
120 }
122 private void writeDetails(int pc) {
123 if (map == null)
124 return;
126 StackMap m = map.get(pc);
127 if (m != null) {
128 print("StackMap locals: ", m.locals);
129 print("StackMap stack: ", m.stack);
130 }
132 }
134 void print(String label, verification_type_info[] entries) {
135 print(label);
136 for (int i = 0; i < entries.length; i++) {
137 print(" ");
138 print(entries[i]);
139 }
140 println();
141 }
143 void print(verification_type_info entry) {
144 if (entry == null) {
145 print("ERROR");
146 return;
147 }
149 switch (entry.tag) {
150 case -1:
151 print(((CustomVerificationTypeInfo) entry).text);
152 break;
154 case ITEM_Top:
155 print("top");
156 break;
158 case ITEM_Integer:
159 print("int");
160 break;
162 case ITEM_Float:
163 print("float");
164 break;
166 case ITEM_Long:
167 print("long");
168 break;
170 case ITEM_Double:
171 print("double");
172 break;
174 case ITEM_Null:
175 print("null");
176 break;
178 case ITEM_UninitializedThis:
179 print("uninit_this");
180 break;
182 case ITEM_Object:
183 try {
184 ConstantPool cp = classWriter.getClassFile().constant_pool;
185 ConstantPool.CONSTANT_Class_info class_info = cp.getClassInfo(((Object_variable_info) entry).cpool_index);
186 print(cp.getUTF8Value(class_info.name_index));
187 } catch (ConstantPoolException e) {
188 print("??");
189 }
190 break;
192 case ITEM_Uninitialized:
193 print(((Uninitialized_variable_info) entry).offset);
194 break;
195 }
197 }
199 private Map<Integer, StackMap> map;
200 private ClassWriter classWriter;
202 class StackMapBuilder
203 implements StackMapTable_attribute.stack_map_frame.Visitor<Integer, Integer> {
205 public Integer visit_same_frame(same_frame frame, Integer pc) {
206 int new_pc = pc + frame.getOffsetDelta() + 1;
207 StackMap m = map.get(pc);
208 assert (m != null);
209 map.put(new_pc, m);
210 return new_pc;
211 }
213 public Integer visit_same_locals_1_stack_item_frame(same_locals_1_stack_item_frame frame, Integer pc) {
214 int new_pc = pc + frame.getOffsetDelta() + 1;
215 StackMap prev = map.get(pc);
216 assert (prev != null);
217 StackMap m = new StackMap(prev.locals, frame.stack);
218 map.put(new_pc, m);
219 return new_pc;
220 }
222 public Integer visit_same_locals_1_stack_item_frame_extended(same_locals_1_stack_item_frame_extended frame, Integer pc) {
223 int new_pc = pc + frame.getOffsetDelta() + 1;
224 StackMap prev = map.get(pc);
225 assert (prev != null);
226 StackMap m = new StackMap(prev.locals, frame.stack);
227 map.put(new_pc, m);
228 return new_pc;
229 }
231 public Integer visit_chop_frame(chop_frame frame, Integer pc) {
232 int new_pc = pc + frame.getOffsetDelta() + 1;
233 StackMap prev = map.get(pc);
234 assert (prev != null);
235 int k = 251 - frame.frame_type;
236 verification_type_info[] new_locals = new verification_type_info[prev.locals.length - k];
237 System.arraycopy(prev.locals, 0, new_locals, 0, new_locals.length);
238 StackMap m = new StackMap(new_locals, empty);
239 map.put(new_pc, m);
240 return new_pc;
241 }
243 public Integer visit_same_frame_extended(same_frame_extended frame, Integer pc) {
244 int new_pc = pc + frame.getOffsetDelta();
245 StackMap m = map.get(pc);
246 assert (m != null);
247 map.put(new_pc, m);
248 return new_pc;
249 }
251 public Integer visit_append_frame(append_frame frame, Integer pc) {
252 int new_pc = pc + frame.getOffsetDelta() + 1;
253 StackMap prev = map.get(pc);
254 assert (prev != null);
255 verification_type_info[] new_locals = new verification_type_info[prev.locals.length + frame.locals.length];
256 System.arraycopy(prev.locals, 0, new_locals, 0, prev.locals.length);
257 System.arraycopy(frame.locals, 0, new_locals, prev.locals.length, frame.locals.length);
258 StackMap m = new StackMap(new_locals, empty);
259 map.put(new_pc, m);
260 return new_pc;
261 }
263 public Integer visit_full_frame(full_frame frame, Integer pc) {
264 int new_pc = pc + frame.getOffsetDelta() + 1;
265 StackMap m = new StackMap(frame.locals, frame.stack);
266 map.put(new_pc, m);
267 return new_pc;
268 }
270 }
272 class StackMap {
273 StackMap(verification_type_info[] locals, verification_type_info[] stack) {
274 this.locals = locals;
275 this.stack = stack;
276 }
278 private final verification_type_info[] locals;
279 private final verification_type_info[] stack;
280 }
282 class CustomVerificationTypeInfo extends verification_type_info {
283 public CustomVerificationTypeInfo(String text) {
284 super(-1);
285 this.text = text;
286 }
287 private String text;
288 }
290 private final verification_type_info[] empty = { };
291 }