1 /*
2 * Copyright (c) 2007, 2009, 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
30 /**
31 * See JVMS, section 4.8.4.
32 *
33 * <p><b>This is NOT part of any supported API.
34 * If you write code that depends on this, you do so at your own risk.
35 * This code and its internal interfaces are subject to change or
36 * deletion without notice.</b>
37 */
38 public class StackMapTable_attribute extends Attribute {
39 static class InvalidStackMap extends AttributeException {
40 private static final long serialVersionUID = -5659038410855089780L;
41 InvalidStackMap(String msg) {
42 super(msg);
43 }
44 }
45
46 StackMapTable_attribute(ClassReader cr, int name_index, int length)
47 throws IOException, InvalidStackMap {
48 super(name_index, length);
49 number_of_entries = cr.readUnsignedShort();
50 entries = new stack_map_frame[number_of_entries];
51 for (int i = 0; i < number_of_entries; i++)
52 entries[i] = stack_map_frame.read(cr);
53 }
54
55 public StackMapTable_attribute(ConstantPool constant_pool, stack_map_frame[] entries)
56 throws ConstantPoolException {
57 this(constant_pool.getUTF8Index(Attribute.StackMapTable), entries);
58 }
59
60 public StackMapTable_attribute(int name_index, stack_map_frame[] entries) {
61 super(name_index, length(entries));
62 this.number_of_entries = entries.length;
63 this.entries = entries;
64 }
65
66 public <R, D> R accept(Visitor<R, D> visitor, D data) {
67 return visitor.visitStackMapTable(this, data);
68 }
69
70 static int length(stack_map_frame[] entries) {
71 int n = 2;
72 for (stack_map_frame entry: entries)
73 n += entry.length();
74 return n;
75 }
76
77 public final int number_of_entries;
78 public final stack_map_frame entries[];
79
80 public abstract static class stack_map_frame {
81 static stack_map_frame read(ClassReader cr)
82 throws IOException, InvalidStackMap {
83 int frame_type = cr.readUnsignedByte();
84 if (frame_type <= 63)
85 return new same_frame(frame_type);
86 else if (frame_type <= 127)
87 return new same_locals_1_stack_item_frame(frame_type, cr);
88 else if (frame_type <= 246)
89 throw new Error("unknown frame_type " + frame_type);
90 else if (frame_type == 247)
91 return new same_locals_1_stack_item_frame_extended(frame_type, cr);
92 else if (frame_type <= 250)
93 return new chop_frame(frame_type, cr);
94 else if (frame_type == 251)
95 return new same_frame_extended(frame_type, cr);
96 else if (frame_type <= 254)
97 return new append_frame(frame_type, cr);
98 else
99 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 int getOffsetDelta();
111
112 public abstract <R,D> R accept(Visitor<R,D> visitor, D data);
113
114 public final int frame_type;
115
116 public static interface Visitor<R,P> {
117 R visit_same_frame(same_frame frame, P p);
118 R visit_same_locals_1_stack_item_frame(same_locals_1_stack_item_frame frame, P p);
119 R visit_same_locals_1_stack_item_frame_extended(same_locals_1_stack_item_frame_extended frame, P p);
120 R visit_chop_frame(chop_frame frame, P p);
121 R visit_same_frame_extended(same_frame_extended frame, P p);
122 R visit_append_frame(append_frame frame, P p);
123 R visit_full_frame(full_frame frame, P p);
124 }
125 }
126
127 public static class same_frame extends stack_map_frame {
128 same_frame(int frame_type) {
129 super(frame_type);
130 }
131
132 public <R, D> R accept(Visitor<R, D> visitor, D data) {
133 return visitor.visit_same_frame(this, data);
134 }
135
136 public int getOffsetDelta() {
137 return frame_type;
138 }
139 }
140
141 public static class same_locals_1_stack_item_frame extends stack_map_frame {
142 same_locals_1_stack_item_frame(int frame_type, ClassReader cr)
143 throws IOException, InvalidStackMap {
144 super(frame_type);
145 stack = new verification_type_info[1];
146 stack[0] = verification_type_info.read(cr);
147 }
148
149 @Override
150 public int length() {
151 return super.length() + stack[0].length();
152 }
153
154 public <R, D> R accept(Visitor<R, D> visitor, D data) {
155 return visitor.visit_same_locals_1_stack_item_frame(this, data);
156 }
157
158 public int getOffsetDelta() {
159 return frame_type - 64;
160 }
161
162 public final verification_type_info[] stack;
163 }
164
165 public static class same_locals_1_stack_item_frame_extended extends stack_map_frame {
166 same_locals_1_stack_item_frame_extended(int frame_type, ClassReader cr)
167 throws IOException, InvalidStackMap {
168 super(frame_type);
169 offset_delta = cr.readUnsignedShort();
170 stack = new verification_type_info[1];
171 stack[0] = verification_type_info.read(cr);
172 }
173
174 @Override
175 public int length() {
176 return super.length() + 2 + stack[0].length();
177 }
178
179 public <R, D> R accept(Visitor<R, D> visitor, D data) {
180 return visitor.visit_same_locals_1_stack_item_frame_extended(this, data);
181 }
182
183 public int getOffsetDelta() {
184 return offset_delta;
185 }
186
187 public final int offset_delta;
188 public final verification_type_info[] stack;
189 }
190
191 public static class chop_frame extends stack_map_frame {
192 chop_frame(int frame_type, ClassReader cr) throws IOException {
193 super(frame_type);
194 offset_delta = cr.readUnsignedShort();
195 }
196
197 @Override
198 public int length() {
199 return super.length() + 2;
200 }
201
202 public <R, D> R accept(Visitor<R, D> visitor, D data) {
203 return visitor.visit_chop_frame(this, data);
204 }
205
206 public int getOffsetDelta() {
207 return offset_delta;
208 }
209
210 public final int offset_delta;
211 }
212
213 public static class same_frame_extended extends stack_map_frame {
214 same_frame_extended(int frame_type, ClassReader cr) throws IOException {
215 super(frame_type);
216 offset_delta = cr.readUnsignedShort();
217 }
218
219 @Override
220 public int length() {
221 return super.length() + 2;
222 }
223
224 public <R, D> R accept(Visitor<R, D> visitor, D data) {
225 return visitor.visit_same_frame_extended(this, data);
226 }
227
228 public int getOffsetDelta() {
229 return offset_delta;
230 }
231
232 public final int offset_delta;
233 }
234
235 public static class append_frame extends stack_map_frame {
236 append_frame(int frame_type, ClassReader cr)
237 throws IOException, InvalidStackMap {
238 super(frame_type);
239 offset_delta = cr.readUnsignedShort();
240 locals = new verification_type_info[frame_type - 251];
241 for (int i = 0; i < locals.length; i++)
242 locals[i] = verification_type_info.read(cr);
243 }
244
245 @Override
246 public int length() {
247 int n = super.length() + 2;
248 for (verification_type_info local: locals)
249 n += local.length();
250 return n;
251 }
252
253 public <R, D> R accept(Visitor<R, D> visitor, D data) {
254 return visitor.visit_append_frame(this, data);
255 }
256
257 public int getOffsetDelta() {
258 return offset_delta;
259 }
260
261 public final int offset_delta;
262 public final verification_type_info[] locals;
263 }
264
265 public static class full_frame extends stack_map_frame {
266 full_frame(int frame_type, ClassReader cr)
267 throws IOException, InvalidStackMap {
268 super(frame_type);
269 offset_delta = cr.readUnsignedShort();
270 number_of_locals = cr.readUnsignedShort();
271 locals = new verification_type_info[number_of_locals];
272 for (int i = 0; i < locals.length; i++)
273 locals[i] = verification_type_info.read(cr);
274 number_of_stack_items = cr.readUnsignedShort();
275 stack = new verification_type_info[number_of_stack_items];
276 for (int i = 0; i < stack.length; i++)
277 stack[i] = verification_type_info.read(cr);
278 }
279
280 @Override
281 public int length() {
282 int n = super.length() + 2;
283 for (verification_type_info local: locals)
284 n += local.length();
285 n += 2;
286 for (verification_type_info item: stack)
287 n += item.length();
288 return n;
289 }
290
291 public <R, D> R accept(Visitor<R, D> visitor, D data) {
292 return visitor.visit_full_frame(this, data);
293 }
294
295 public int getOffsetDelta() {
296 return offset_delta;
297 }
298
299 public final int offset_delta;
300 public final int number_of_locals;
301 public final verification_type_info[] locals;
302 public final int number_of_stack_items;
303 public final verification_type_info[] stack;
304 }
305
306 public static class verification_type_info {
307 public static final int ITEM_Top = 0;
308 public static final int ITEM_Integer = 1;
309 public static final int ITEM_Float = 2;
310 public static final int ITEM_Long = 4;
311 public static final int ITEM_Double = 3;
312 public static final int ITEM_Null = 5;
313 public static final int ITEM_UninitializedThis = 6;
314 public static final int ITEM_Object = 7;
315 public static final int ITEM_Uninitialized = 8;
316
317 static verification_type_info read(ClassReader cr)
318 throws IOException, InvalidStackMap {
319 int tag = cr.readUnsignedByte();
320 switch (tag) {
321 case ITEM_Top:
322 case ITEM_Integer:
323 case ITEM_Float:
324 case ITEM_Long:
325 case ITEM_Double:
|
1 /*
2 * Copyright (c) 2007, 2025, 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
30 /**
31 * See JVMS, section 4.8.4.
32 *
33 * <p><b>This is NOT part of any supported API.
34 * If you write code that depends on this, you do so at your own risk.
35 * This code and its internal interfaces are subject to change or
36 * deletion without notice.</b>
37 */
38 public class StackMapTable_attribute extends Attribute {
39 static class InvalidStackMap extends AttributeException {
40 private static final long serialVersionUID = -5659038410855089780L;
41 InvalidStackMap(String msg) {
42 super(msg);
43 }
44 }
45
46 StackMapTable_attribute(ClassReader cr, int name_index, int length)
47 throws IOException, InvalidStackMap {
48 super(name_index, length);
49 number_of_entries = cr.readUnsignedShort();
50 entries = new stack_map_entry[number_of_entries];
51 for (int i = 0; i < number_of_entries; i++)
52 entries[i] = stack_map_entry.read(cr);
53 }
54
55 public StackMapTable_attribute(ConstantPool constant_pool, stack_map_entry[] entries)
56 throws ConstantPoolException {
57 this(constant_pool.getUTF8Index(Attribute.StackMapTable), entries);
58 }
59
60 public StackMapTable_attribute(int name_index, stack_map_entry[] entries) {
61 super(name_index, length(entries));
62 this.number_of_entries = entries.length;
63 this.entries = entries;
64 }
65
66 public <R, D> R accept(Visitor<R, D> visitor, D data) {
67 return visitor.visitStackMapTable(this, data);
68 }
69
70 static int length(stack_map_entry[] entries) {
71 int n = 2;
72 for (stack_map_entry entry: entries)
73 n += entry.length();
74 return n;
75 }
76
77 public final int number_of_entries;
78 public final stack_map_entry entries[];
79
80 public abstract static class stack_map_entry {
81 static stack_map_entry read(ClassReader cr)
82 throws IOException, InvalidStackMap {
83 int entry_type = cr.readUnsignedByte();
84 if (entry_type <= 63)
85 return new same_frame(entry_type);
86 else if (entry_type <= 127)
87 return new same_locals_1_stack_item_frame(entry_type, cr);
88 else if (entry_type <= 245)
89 throw new Error("unknown frame_type " + entry_type);
90 else if (entry_type == 246)
91 return new assert_unset_fields(entry_type, cr);
92 else if (entry_type == 247)
93 return new same_locals_1_stack_item_frame_extended(entry_type, cr);
94 else if (entry_type <= 250)
95 return new chop_frame(entry_type, cr);
96 else if (entry_type == 251)
97 return new same_frame_extended(entry_type, cr);
98 else if (entry_type <= 254)
99 return new append_frame(entry_type, cr);
100 else
101 return new full_frame(entry_type, cr);
102 }
103
104 protected stack_map_entry(int entry_type) {
105 this.entry_type = entry_type;
106 }
107
108 public int length() {
109 return 1;
110 }
111
112 public abstract <R,D> R accept(Visitor<R,D> visitor, D data);
113
114 public final int entry_type;
115
116 public interface Visitor<R,P> {
117 R visit_same_frame(same_frame frame, P p);
118 R visit_same_locals_1_stack_item_frame(same_locals_1_stack_item_frame frame, P p);
119 R visit_same_locals_1_stack_item_frame_extended(same_locals_1_stack_item_frame_extended frame, P p);
120 R visit_chop_frame(chop_frame frame, P p);
121 R visit_same_frame_extended(same_frame_extended frame, P p);
122 R visit_append_frame(append_frame frame, P p);
123 R visit_full_frame(full_frame frame, P p);
124 R visit_assert_unset_fields(assert_unset_fields frame, P p);
125 }
126 }
127
128 public static class same_frame extends stack_map_entry {
129 same_frame(int entry_type) {
130 super(entry_type);
131 }
132
133 public <R, D> R accept(Visitor<R, D> visitor, D data) {
134 return visitor.visit_same_frame(this, data);
135 }
136 }
137
138 public static class same_locals_1_stack_item_frame extends stack_map_entry {
139 same_locals_1_stack_item_frame(int entry_type, ClassReader cr)
140 throws IOException, InvalidStackMap {
141 super(entry_type);
142 stack = new verification_type_info[1];
143 stack[0] = verification_type_info.read(cr);
144 }
145
146 @Override
147 public int length() {
148 return super.length() + stack[0].length();
149 }
150
151 public <R, D> R accept(Visitor<R, D> visitor, D data) {
152 return visitor.visit_same_locals_1_stack_item_frame(this, data);
153 }
154
155 public final verification_type_info[] stack;
156 }
157
158 public static class same_locals_1_stack_item_frame_extended extends stack_map_entry {
159 same_locals_1_stack_item_frame_extended(int entry_type, ClassReader cr)
160 throws IOException, InvalidStackMap {
161 super(entry_type);
162 offset_delta = cr.readUnsignedShort();
163 stack = new verification_type_info[1];
164 stack[0] = verification_type_info.read(cr);
165 }
166
167 @Override
168 public int length() {
169 return super.length() + 2 + stack[0].length();
170 }
171
172 public <R, D> R accept(Visitor<R, D> visitor, D data) {
173 return visitor.visit_same_locals_1_stack_item_frame_extended(this, data);
174 }
175
176 public final int offset_delta;
177 public final verification_type_info[] stack;
178 }
179
180 public static class chop_frame extends stack_map_entry {
181 chop_frame(int entry_type, ClassReader cr) throws IOException {
182 super(entry_type);
183 offset_delta = cr.readUnsignedShort();
184 }
185
186 @Override
187 public int length() {
188 return super.length() + 2;
189 }
190
191 public <R, D> R accept(Visitor<R, D> visitor, D data) {
192 return visitor.visit_chop_frame(this, data);
193 }
194
195 public final int offset_delta;
196 }
197
198 public static class same_frame_extended extends stack_map_entry {
199 same_frame_extended(int entry_type, ClassReader cr) throws IOException {
200 super(entry_type);
201 offset_delta = cr.readUnsignedShort();
202 }
203
204 @Override
205 public int length() {
206 return super.length() + 2;
207 }
208
209 public <R, D> R accept(Visitor<R, D> visitor, D data) {
210 return visitor.visit_same_frame_extended(this, data);
211 }
212
213 public final int offset_delta;
214 }
215
216 public static class append_frame extends stack_map_entry {
217 append_frame(int entry_type, ClassReader cr)
218 throws IOException, InvalidStackMap {
219 super(entry_type);
220 offset_delta = cr.readUnsignedShort();
221 locals = new verification_type_info[entry_type - 251];
222 for (int i = 0; i < locals.length; i++)
223 locals[i] = verification_type_info.read(cr);
224 }
225
226 @Override
227 public int length() {
228 int n = super.length() + 2;
229 for (verification_type_info local: locals)
230 n += local.length();
231 return n;
232 }
233
234 public <R, D> R accept(Visitor<R, D> visitor, D data) {
235 return visitor.visit_append_frame(this, data);
236 }
237
238 public final int offset_delta;
239 public final verification_type_info[] locals;
240 }
241
242 public static class full_frame extends stack_map_entry {
243 full_frame(int entry_type, ClassReader cr)
244 throws IOException, InvalidStackMap {
245 super(entry_type);
246 offset_delta = cr.readUnsignedShort();
247 number_of_locals = cr.readUnsignedShort();
248 locals = new verification_type_info[number_of_locals];
249 for (int i = 0; i < locals.length; i++)
250 locals[i] = verification_type_info.read(cr);
251 number_of_stack_items = cr.readUnsignedShort();
252 stack = new verification_type_info[number_of_stack_items];
253 for (int i = 0; i < stack.length; i++)
254 stack[i] = verification_type_info.read(cr);
255 }
256
257 @Override
258 public int length() {
259 int n = super.length() + 2;
260 for (verification_type_info local: locals)
261 n += local.length();
262 n += 2;
263 for (verification_type_info item: stack)
264 n += item.length();
265 return n;
266 }
267
268 public <R, D> R accept(Visitor<R, D> visitor, D data) {
269 return visitor.visit_full_frame(this, data);
270 }
271
272 public final int offset_delta;
273 public final int number_of_locals;
274 public final verification_type_info[] locals;
275 public final int number_of_stack_items;
276 public final verification_type_info[] stack;
277 }
278
279 public static class assert_unset_fields extends stack_map_entry {
280 assert_unset_fields(int entry_type, ClassReader cr) throws IOException {
281 super(entry_type);
282 number_of_unset_fields = cr.readUnsignedShort();
283 unset_fields = new int[number_of_unset_fields];
284 for (int i = 0; i < number_of_unset_fields; i++) {
285 unset_fields[i] = cr.readUnsignedShort();
286 }
287 }
288
289 public <R, D> R accept(Visitor<R, D> visitor, D data) {
290 return visitor.visit_assert_unset_fields(this, data);
291 }
292
293 public final int number_of_unset_fields;
294 public final int[] unset_fields;
295 }
296
297 public static class verification_type_info {
298 public static final int ITEM_Top = 0;
299 public static final int ITEM_Integer = 1;
300 public static final int ITEM_Float = 2;
301 public static final int ITEM_Long = 4;
302 public static final int ITEM_Double = 3;
303 public static final int ITEM_Null = 5;
304 public static final int ITEM_UninitializedThis = 6;
305 public static final int ITEM_Object = 7;
306 public static final int ITEM_Uninitialized = 8;
307
308 static verification_type_info read(ClassReader cr)
309 throws IOException, InvalidStackMap {
310 int tag = cr.readUnsignedByte();
311 switch (tag) {
312 case ITEM_Top:
313 case ITEM_Integer:
314 case ITEM_Float:
315 case ITEM_Long:
316 case ITEM_Double:
|