001 /*
002 * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation. Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025
026 package com.sun.tools.classfile;
027
028 import java.io.IOException;
029
030 /**
031 * See JVMS3, section 4.8.4.
032 *
033 * <p><b>This is NOT part of any API supported by Sun Microsystems. If
034 * you write code that depends on this, you do so at your own risk.
035 * This code and its internal interfaces are subject to change or
036 * deletion without notice.</b>
037 */
038 public class StackMapTable_attribute extends Attribute {
039 static class InvalidStackMap extends AttributeException {
040 private static final long serialVersionUID = -5659038410855089780L;
041 InvalidStackMap(String msg) {
042 super(msg);
043 }
044 }
045
046 StackMapTable_attribute(ClassReader cr, int name_index, int length)
047 throws IOException, InvalidStackMap {
048 super(name_index, length);
049 number_of_entries = cr.readUnsignedShort();
050 entries = new stack_map_frame[number_of_entries];
051 for (int i = 0; i < number_of_entries; i++)
052 entries[i] = stack_map_frame.read(cr);
053 }
054
055 public StackMapTable_attribute(ConstantPool constant_pool, stack_map_frame[] entries)
056 throws ConstantPoolException {
057 this(constant_pool.getUTF8Index(Attribute.StackMapTable), entries);
058 }
059
060 public StackMapTable_attribute(int name_index, stack_map_frame[] entries) {
061 super(name_index, length(entries));
062 this.number_of_entries = entries.length;
063 this.entries = entries;
064 }
065
066 public <R, D> R accept(Visitor<R, D> visitor, D data) {
067 return visitor.visitStackMapTable(this, data);
068 }
069
070 static int length(stack_map_frame[] entries) {
071 int n = 2;
072 for (stack_map_frame entry: entries)
073 n += entry.length();
074 return n;
075 }
076
077 public final int number_of_entries;
078 public final stack_map_frame entries[];
079
080 public static abstract class stack_map_frame {
081 static stack_map_frame read(ClassReader cr)
082 throws IOException, InvalidStackMap {
083 int frame_type = cr.readUnsignedByte();
084 if (frame_type <= 63)
085 return new same_frame(frame_type);
086 else if (frame_type <= 127)
087 return new same_locals_1_stack_item_frame(frame_type, cr);
088 else if (frame_type <= 246)
089 throw new Error("unknown frame_type " + frame_type);
090 else if (frame_type == 247)
091 return new same_locals_1_stack_item_frame_extended(frame_type, cr);
092 else if (frame_type <= 250)
093 return new chop_frame(frame_type, cr);
094 else if (frame_type == 251)
095 return new same_frame_extended(frame_type, cr);
096 else if (frame_type <= 254)
097 return new append_frame(frame_type, cr);
098 else
099 return new full_frame(frame_type, cr);
100 }
101
102 protected stack_map_frame(int frame_type) {
103 this.frame_type = frame_type;
104 }
105
106 public int length() {
107 return 1;
108 }
109
110 public abstract <R,D> R accept(Visitor<R,D> visitor, D data);
111
112 public final int frame_type;
113
114 public static interface Visitor<R,P> {
115 R visit_same_frame(same_frame frame, P p);
116 R visit_same_locals_1_stack_item_frame(same_locals_1_stack_item_frame frame, P p);
117 R visit_same_locals_1_stack_item_frame_extended(same_locals_1_stack_item_frame_extended frame, P p);
118 R visit_chop_frame(chop_frame frame, P p);
119 R visit_same_frame_extended(same_frame_extended frame, P p);
120 R visit_append_frame(append_frame frame, P p);
121 R visit_full_frame(full_frame frame, P p);
122 }
123 }
124
125 public static class same_frame extends stack_map_frame {
126 same_frame(int frame_type) {
127 super(frame_type);
128 }
129
130 public <R, D> R accept(Visitor<R, D> visitor, D data) {
131 return visitor.visit_same_frame(this, data);
132 }
133 }
134
135 public static class same_locals_1_stack_item_frame extends stack_map_frame {
136 same_locals_1_stack_item_frame(int frame_type, ClassReader cr)
137 throws IOException, InvalidStackMap {
138 super(frame_type);
139 stack = new verification_type_info[1];
140 stack[0] = verification_type_info.read(cr);
141 }
142
143 @Override
144 public int length() {
145 return super.length() + stack[0].length();
146 }
147
148 public <R, D> R accept(Visitor<R, D> visitor, D data) {
149 return visitor.visit_same_locals_1_stack_item_frame(this, data);
150 }
151
152 public final verification_type_info[] stack;
153 }
154
155 public static class same_locals_1_stack_item_frame_extended extends stack_map_frame {
156 same_locals_1_stack_item_frame_extended(int frame_type, ClassReader cr)
157 throws IOException, InvalidStackMap {
158 super(frame_type);
159 offset_delta = cr.readUnsignedShort();
160 stack = new verification_type_info[1];
161 stack[0] = verification_type_info.read(cr);
162 }
163
164 @Override
165 public int length() {
166 return super.length() + 2 + stack[0].length();
167 }
168
169 public <R, D> R accept(Visitor<R, D> visitor, D data) {
170 return visitor.visit_same_locals_1_stack_item_frame_extended(this, data);
171 }
172
173 public final int offset_delta;
174 public final verification_type_info[] stack;
175 }
176
177 public static class chop_frame extends stack_map_frame {
178 chop_frame(int frame_type, ClassReader cr) throws IOException {
179 super(frame_type);
180 offset_delta = cr.readUnsignedShort();
181 }
182
183 @Override
184 public int length() {
185 return super.length() + 2;
186 }
187
188 public <R, D> R accept(Visitor<R, D> visitor, D data) {
189 return visitor.visit_chop_frame(this, data);
190 }
191
192 public final int offset_delta;
193 }
194
195 public static class same_frame_extended extends stack_map_frame {
196 same_frame_extended(int frame_type, ClassReader cr) throws IOException {
197 super(frame_type);
198 offset_delta = cr.readUnsignedShort();
199 }
200
201 @Override
202 public int length() {
203 return super.length() + 2;
204 }
205
206 public <R, D> R accept(Visitor<R, D> visitor, D data) {
207 return visitor.visit_same_frame_extended(this, data);
208 }
209
210 public final int offset_delta;
211 }
212
213 public static class append_frame extends stack_map_frame {
214 append_frame(int frame_type, ClassReader cr)
215 throws IOException, InvalidStackMap {
216 super(frame_type);
217 offset_delta = cr.readUnsignedShort();
218 locals = new verification_type_info[frame_type - 251];
219 for (int i = 0; i < locals.length; i++)
220 locals[i] = verification_type_info.read(cr);
221 }
222
223 @Override
224 public int length() {
225 int n = super.length() + 2;
226 for (verification_type_info local: locals)
227 n += local.length();
228 return n;
229 }
230
231 public <R, D> R accept(Visitor<R, D> visitor, D data) {
232 return visitor.visit_append_frame(this, data);
233 }
234
235 public final int offset_delta;
236 public final verification_type_info[] locals;
237 }
238
239 public static class full_frame extends stack_map_frame {
240 full_frame(int frame_type, ClassReader cr)
241 throws IOException, InvalidStackMap {
242 super(frame_type);
243 offset_delta = cr.readUnsignedShort();
244 number_of_locals = cr.readUnsignedShort();
245 locals = new verification_type_info[number_of_locals];
246 for (int i = 0; i < locals.length; i++)
247 locals[i] = verification_type_info.read(cr);
248 number_of_stack_items = cr.readUnsignedShort();
249 stack = new verification_type_info[number_of_stack_items];
250 for (int i = 0; i < stack.length; i++)
251 stack[i] = verification_type_info.read(cr);
252 }
253
254 @Override
255 public int length() {
256 int n = super.length() + 2;
257 for (verification_type_info local: locals)
258 n += local.length();
259 n += 2;
260 for (verification_type_info item: stack)
261 n += item.length();
262 return n;
263 }
264
265 public <R, D> R accept(Visitor<R, D> visitor, D data) {
266 return visitor.visit_full_frame(this, data);
267 }
268
269 public final int offset_delta;
270 public final int number_of_locals;
271 public final verification_type_info[] locals;
272 public final int number_of_stack_items;
273 public final verification_type_info[] stack;
274 }
275
276 public static class verification_type_info {
277 public static final int ITEM_Top = 0;
278 public static final int ITEM_Integer = 1;
279 public static final int ITEM_Float = 2;
280 public static final int ITEM_Long = 4;
281 public static final int ITEM_Double = 3;
282 public static final int ITEM_Null = 5;
283 public static final int ITEM_UninitializedThis = 6;
284 public static final int ITEM_Object = 7;
285 public static final int ITEM_Uninitialized = 8;
286
287 static verification_type_info read(ClassReader cr)
288 throws IOException, InvalidStackMap {
289 int tag = cr.readUnsignedByte();
290 switch (tag) {
291 case ITEM_Top:
292 case ITEM_Integer:
293 case ITEM_Float:
294 case ITEM_Long:
295 case ITEM_Double:
296 case ITEM_Null:
297 case ITEM_UninitializedThis:
298 return new verification_type_info(tag);
299
300 case ITEM_Object:
301 return new Object_variable_info(cr);
302
303 case ITEM_Uninitialized:
304 return new Uninitialized_variable_info(cr);
305
306 default:
307 throw new InvalidStackMap("unrecognized verification_type_info tag");
308 }
309 }
310
311 verification_type_info(int tag) {
312 this.tag = tag;
313 }
314
315 public int length() {
316 return 1;
317 }
318
319 public final int tag;
320 }
321
322 public static class Object_variable_info extends verification_type_info {
323 Object_variable_info(ClassReader cr) throws IOException {
324 super(ITEM_Object);
325 cpool_index = cr.readUnsignedShort();
326 }
327
328 @Override
329 public int length() {
330 return super.length() + 2;
331 }
332
333 public final int cpool_index;
334 }
335
336 public static class Uninitialized_variable_info extends verification_type_info {
337 Uninitialized_variable_info(ClassReader cr) throws IOException {
338 super(ITEM_Uninitialized);
339 offset = cr.readUnsignedShort();
340 }
341
342 @Override
343 public int length() {
344 return super.length() + 2;
345 }
346
347 public final int offset;
348
349 }
350 }