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

changeset 0
959103a6100f
child 2525
2eb010b6cb22
equal deleted inserted replaced
-1:000000000000 0:959103a6100f
1 /*
2 * Copyright (c) 2009, 2013, Oracle and/or its affiliates. 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. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package com.sun.tools.javap;
27
28 import java.util.Arrays;
29 import java.util.HashMap;
30 import java.util.Map;
31
32 import com.sun.tools.classfile.AccessFlags;
33 import com.sun.tools.classfile.Attribute;
34 import com.sun.tools.classfile.Code_attribute;
35 import com.sun.tools.classfile.ConstantPool;
36 import com.sun.tools.classfile.ConstantPoolException;
37 import com.sun.tools.classfile.Descriptor;
38 import com.sun.tools.classfile.Descriptor.InvalidDescriptor;
39 import com.sun.tools.classfile.Instruction;
40 import com.sun.tools.classfile.Method;
41 import com.sun.tools.classfile.StackMapTable_attribute;
42 import com.sun.tools.classfile.StackMapTable_attribute.*;
43
44 import static com.sun.tools.classfile.StackMapTable_attribute.verification_type_info.*;
45
46 /**
47 * Annotate instructions with stack map.
48 *
49 * <p><b>This is NOT part of any supported API.
50 * If you write code that depends on this, you do so at your own risk.
51 * This code and its internal interfaces are subject to change or
52 * deletion without notice.</b>
53 */
54 public class StackMapWriter extends InstructionDetailWriter {
55 static StackMapWriter instance(Context context) {
56 StackMapWriter instance = context.get(StackMapWriter.class);
57 if (instance == null)
58 instance = new StackMapWriter(context);
59 return instance;
60 }
61
62 protected StackMapWriter(Context context) {
63 super(context);
64 context.put(StackMapWriter.class, this);
65 classWriter = ClassWriter.instance(context);
66 }
67
68 public void reset(Code_attribute attr) {
69 setStackMap((StackMapTable_attribute) attr.attributes.get(Attribute.StackMapTable));
70 }
71
72 void setStackMap(StackMapTable_attribute attr) {
73 if (attr == null) {
74 map = null;
75 return;
76 }
77
78 Method m = classWriter.getMethod();
79 Descriptor d = m.descriptor;
80 String[] args;
81 try {
82 ConstantPool cp = classWriter.getClassFile().constant_pool;
83 String argString = d.getParameterTypes(cp);
84 args = argString.substring(1, argString.length() - 1).split("[, ]+");
85 } catch (ConstantPoolException e) {
86 return;
87 } catch (InvalidDescriptor e) {
88 return;
89 }
90 boolean isStatic = m.access_flags.is(AccessFlags.ACC_STATIC);
91
92 verification_type_info[] initialLocals = new verification_type_info[(isStatic ? 0 : 1) + args.length];
93 if (!isStatic)
94 initialLocals[0] = new CustomVerificationTypeInfo("this");
95 for (int i = 0; i < args.length; i++) {
96 initialLocals[(isStatic ? 0 : 1) + i] =
97 new CustomVerificationTypeInfo(args[i].replace(".", "/"));
98 }
99
100 map = new HashMap<Integer, StackMap>();
101 StackMapBuilder builder = new StackMapBuilder();
102
103 // using -1 as the pc for the initial frame effectively compensates for
104 // the difference in behavior for the first stack map frame (where the
105 // pc offset is just offset_delta) compared to subsequent frames (where
106 // the pc offset is always offset_delta+1).
107 int pc = -1;
108
109 map.put(pc, new StackMap(initialLocals, empty));
110
111 for (int i = 0; i < attr.entries.length; i++)
112 pc = attr.entries[i].accept(builder, pc);
113 }
114
115 public void writeInitialDetails() {
116 writeDetails(-1);
117 }
118
119 public void writeDetails(Instruction instr) {
120 writeDetails(instr.getPC());
121 }
122
123 private void writeDetails(int pc) {
124 if (map == null)
125 return;
126
127 StackMap m = map.get(pc);
128 if (m != null) {
129 print("StackMap locals: ", m.locals);
130 print("StackMap stack: ", m.stack);
131 }
132
133 }
134
135 void print(String label, verification_type_info[] entries) {
136 print(label);
137 for (int i = 0; i < entries.length; i++) {
138 print(" ");
139 print(entries[i]);
140 }
141 println();
142 }
143
144 void print(verification_type_info entry) {
145 if (entry == null) {
146 print("ERROR");
147 return;
148 }
149
150 switch (entry.tag) {
151 case -1:
152 print(((CustomVerificationTypeInfo) entry).text);
153 break;
154
155 case ITEM_Top:
156 print("top");
157 break;
158
159 case ITEM_Integer:
160 print("int");
161 break;
162
163 case ITEM_Float:
164 print("float");
165 break;
166
167 case ITEM_Long:
168 print("long");
169 break;
170
171 case ITEM_Double:
172 print("double");
173 break;
174
175 case ITEM_Null:
176 print("null");
177 break;
178
179 case ITEM_UninitializedThis:
180 print("uninit_this");
181 break;
182
183 case ITEM_Object:
184 try {
185 ConstantPool cp = classWriter.getClassFile().constant_pool;
186 ConstantPool.CONSTANT_Class_info class_info = cp.getClassInfo(((Object_variable_info) entry).cpool_index);
187 print(cp.getUTF8Value(class_info.name_index));
188 } catch (ConstantPoolException e) {
189 print("??");
190 }
191 break;
192
193 case ITEM_Uninitialized:
194 print(((Uninitialized_variable_info) entry).offset);
195 break;
196 }
197
198 }
199
200 private Map<Integer, StackMap> map;
201 private ClassWriter classWriter;
202
203 class StackMapBuilder
204 implements StackMapTable_attribute.stack_map_frame.Visitor<Integer, Integer> {
205
206 public Integer visit_same_frame(same_frame frame, Integer pc) {
207 int new_pc = pc + frame.getOffsetDelta() + 1;
208 StackMap m = map.get(pc);
209 assert (m != null);
210 map.put(new_pc, m);
211 return new_pc;
212 }
213
214 public Integer visit_same_locals_1_stack_item_frame(same_locals_1_stack_item_frame frame, Integer pc) {
215 int new_pc = pc + frame.getOffsetDelta() + 1;
216 StackMap prev = map.get(pc);
217 assert (prev != null);
218 StackMap m = new StackMap(prev.locals, frame.stack);
219 map.put(new_pc, m);
220 return new_pc;
221 }
222
223 public Integer visit_same_locals_1_stack_item_frame_extended(same_locals_1_stack_item_frame_extended frame, Integer pc) {
224 int new_pc = pc + frame.getOffsetDelta() + 1;
225 StackMap prev = map.get(pc);
226 assert (prev != null);
227 StackMap m = new StackMap(prev.locals, frame.stack);
228 map.put(new_pc, m);
229 return new_pc;
230 }
231
232 public Integer visit_chop_frame(chop_frame frame, Integer pc) {
233 int new_pc = pc + frame.getOffsetDelta() + 1;
234 StackMap prev = map.get(pc);
235 assert (prev != null);
236 int k = 251 - frame.frame_type;
237 verification_type_info[] new_locals = Arrays.copyOf(prev.locals, prev.locals.length - k);
238 StackMap m = new StackMap(new_locals, empty);
239 map.put(new_pc, m);
240 return new_pc;
241 }
242
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 }
250
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 }
262
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 }
269
270 }
271
272 static class StackMap {
273 StackMap(verification_type_info[] locals, verification_type_info[] stack) {
274 this.locals = locals;
275 this.stack = stack;
276 }
277
278 private final verification_type_info[] locals;
279 private final verification_type_info[] stack;
280 }
281
282 static class CustomVerificationTypeInfo extends verification_type_info {
283 public CustomVerificationTypeInfo(String text) {
284 super(-1);
285 this.text = text;
286 }
287 private String text;
288 }
289
290 private final verification_type_info[] empty = { };
291 }

mercurial