Line data Source code
1 : /* src/vm/stackmap.c - class attribute StackMapTable
2 :
3 : Copyright (C) 1996-2013
4 : CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5 :
6 : This file is part of CACAO.
7 :
8 : This program is free software; you can redistribute it and/or
9 : modify it under the terms of the GNU General Public License as
10 : published by the Free Software Foundation; either version 2, or (at
11 : your option) any later version.
12 :
13 : This program is distributed in the hope that it will be useful, but
14 : WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 : General Public License for more details.
17 :
18 : You should have received a copy of the GNU General Public License
19 : along with this program; if not, write to the Free Software
20 : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 : 02110-1301, USA.
22 :
23 : */
24 :
25 :
26 : #include "config.h"
27 : #include "vm/types.hpp"
28 :
29 : #include "mm/dumpmemory.hpp"
30 :
31 : #include "vm/exceptions.hpp"
32 : #include "vm/stackmap.hpp"
33 : #include "vm/statistics.hpp"
34 : #include "vm/options.hpp"
35 : #include "vm/suck.hpp"
36 :
37 : STAT_DECLARE_VAR(int,size_stack_map,0)
38 :
39 : struct classinfo;
40 :
41 : using namespace cacao;
42 :
43 :
44 : /* stackmap_get_verification_type_info *****************************************
45 :
46 : union verification_type_info {
47 : Top_variable_info;
48 : Integer_variable_info;
49 : Float_variable_info;
50 : Long_variable_info;
51 : Double_variable_info;
52 : Null_variable_info;
53 : UninitializedThis_variable_info;
54 : Object_variable_info;
55 : Uninitialized_variable_info;
56 : }
57 :
58 : Top_variable_info {
59 : u1 tag = ITEM_Top; // 0
60 : }
61 :
62 : Integer_variable_info {
63 : u1 tag = ITEM_Integer; // 1
64 : }
65 :
66 : Float_variable_info {
67 : u1 tag = ITEM_Float; // 2
68 : }
69 :
70 : Long_variable_info {
71 : u1 tag = ITEM_Long; // 4
72 : }
73 :
74 : Double_variable_info {
75 : u1 tag = ITEM_Double; // 3
76 : }
77 :
78 : Null_variable_info {
79 : u1 tag = ITEM_Null; // 5
80 : }
81 :
82 : UninitializedThis_variable_info {
83 : u1 tag = ITEM_UninitializedThis; // 6
84 : }
85 :
86 : Object_variable_info {
87 : u1 tag = ITEM_Object; // 7
88 : u2 cpool_index;
89 : }
90 :
91 : Uninitialized_variable_info {
92 : u1 tag = ITEM_Uninitialized; // 8
93 : u2 offset;
94 : }
95 :
96 : *******************************************************************************/
97 :
98 449857 : static bool stackmap_get_verification_type_info(ClassBuffer& cb, verification_type_info_t *verification_type_info)
99 : {
100 : /* get verification type */
101 :
102 449857 : if (!cb.check_size(1))
103 0 : return false;
104 :
105 449857 : verification_type_info->tag = cb.read_u1();
106 :
107 : /* process the tag */
108 :
109 449857 : switch (verification_type_info->tag) {
110 : case ITEM_Top:
111 : case ITEM_Integer:
112 : case ITEM_Float:
113 : case ITEM_Long:
114 : case ITEM_Double:
115 : case ITEM_Null:
116 : case ITEM_UninitializedThis:
117 171430 : break;
118 :
119 : case ITEM_Object:
120 : /* get constant pool index */
121 :
122 274723 : if (!cb.check_size(2))
123 0 : return false;
124 :
125 274723 : verification_type_info->Object_variable_info.cpool_index = cb.read_u2();
126 274723 : break;
127 :
128 : case ITEM_Uninitialized:
129 : /* get offset */
130 :
131 3704 : if (!cb.check_size(2))
132 0 : return false;
133 :
134 3704 : verification_type_info->Uninitialized_variable_info.offset = cb.read_u2();
135 : break;
136 : }
137 :
138 449857 : return true;
139 : }
140 :
141 :
142 : /* stackmap_get_same_locals_1_stack_item_frame *********************************
143 :
144 : same_locals_1_stack_item_frame {
145 : u1 frame_type = SAME_LOCALS_1_STACK_ITEM; // 64-127
146 : verification_type_info stack[1];
147 : }
148 :
149 : *******************************************************************************/
150 :
151 34593 : static bool stackmap_get_same_locals_1_stack_item_frame(ClassBuffer& cb, stack_map_frame_t *stack_map_frame)
152 : {
153 : same_locals_1_stack_item_frame_t *same_locals_1_stack_item_frame;
154 :
155 : /* for convenience */
156 :
157 : same_locals_1_stack_item_frame =
158 34593 : &(stack_map_frame->same_locals_1_stack_item_frame);
159 :
160 34593 : if (!stackmap_get_verification_type_info(cb, &(same_locals_1_stack_item_frame->stack[0])))
161 0 : return false;
162 :
163 34593 : return true;
164 : }
165 :
166 :
167 : /* stackmap_get_same_locals_1_stack_item_frame_extended ************************
168 :
169 : same_locals_1_stack_item_frame_extended {
170 : u1 frame_type = SAME_LOCALS_1_STACK_ITEM_EXTENDED; // 247
171 : u2 offset_delta;
172 : verification_type_info stack[1];
173 : }
174 :
175 : *******************************************************************************/
176 :
177 148 : static bool stackmap_get_same_locals_1_stack_item_frame_extended(ClassBuffer& cb, stack_map_frame_t *stack_map_frame)
178 : {
179 : same_locals_1_stack_item_frame_extended_t *same_locals_1_stack_item_frame_extended;
180 :
181 : /* for convenience */
182 :
183 : same_locals_1_stack_item_frame_extended =
184 148 : &(stack_map_frame->same_locals_1_stack_item_frame_extended);
185 :
186 : /* check buffer size */
187 :
188 148 : if (!cb.check_size(2))
189 0 : return false;
190 :
191 : /* get offset delta */
192 :
193 148 : same_locals_1_stack_item_frame_extended->offset_delta = cb.read_u2();
194 :
195 : /* process stack */
196 :
197 148 : if (!stackmap_get_verification_type_info(cb, &(same_locals_1_stack_item_frame_extended->stack[0])))
198 0 : return false;
199 :
200 148 : return true;
201 : }
202 :
203 :
204 : /* stackmap_get_chop_frame *****************************************************
205 :
206 : chop_frame {
207 : u1 frame_type = CHOP_FRAME; // 248-250
208 : u2 offset_delta;
209 : }
210 :
211 : *******************************************************************************/
212 :
213 25393 : static bool stackmap_get_chop_frame(ClassBuffer& cb, stack_map_frame_t *stack_map_frame)
214 : {
215 : chop_frame_t *chop_frame;
216 :
217 : /* for convenience */
218 :
219 25393 : chop_frame = &(stack_map_frame->chop_frame);
220 :
221 : /* check buffer size */
222 :
223 25393 : if (!cb.check_size(2))
224 0 : return false;
225 :
226 : /* get offset delta */
227 :
228 25393 : chop_frame->offset_delta = cb.read_u2();
229 :
230 25393 : return true;
231 : }
232 :
233 :
234 : /* stackmap_get_same_frame_extended ********************************************
235 :
236 : same_frame_extended {
237 : u1 frame_type = SAME_FRAME_EXTENDED; // 251
238 : u2 offset_delta;
239 : }
240 :
241 : *******************************************************************************/
242 :
243 1454 : static bool stackmap_get_same_frame_extended(ClassBuffer& cb,
244 : stack_map_frame_t *stack_map_frame)
245 : {
246 : same_frame_extended_t *same_frame_extended;
247 :
248 : /* for convenience */
249 :
250 1454 : same_frame_extended = &(stack_map_frame->same_frame_extended);
251 :
252 : /* check buffer size */
253 :
254 1454 : if (!cb.check_size(2))
255 0 : return false;
256 :
257 : /* get offset delta */
258 :
259 1454 : same_frame_extended->offset_delta = cb.read_u2();
260 :
261 1454 : return true;
262 : }
263 :
264 :
265 : /* stackmap_get_append_frame ***************************************************
266 :
267 : append_frame {
268 : u1 frame_type = APPEND_FRAME; // 252-254
269 : u2 offset_delta;
270 : verification_type_info locals[frame_Type - 251];
271 : }
272 :
273 : *******************************************************************************/
274 :
275 102850 : static bool stackmap_get_append_frame(ClassBuffer& cb,
276 : stack_map_frame_t *stack_map_frame)
277 : {
278 : append_frame_t *append_frame;
279 : s4 number_of_locals;
280 : s4 i;
281 :
282 : /* for convenience */
283 :
284 102850 : append_frame = &(stack_map_frame->append_frame);
285 :
286 : /* check buffer size */
287 :
288 102850 : if (!cb.check_size(2))
289 0 : return false;
290 :
291 : /* get offset delta */
292 :
293 102850 : append_frame->offset_delta = cb.read_u2();
294 :
295 : /* allocate locals array */
296 :
297 102850 : number_of_locals = append_frame->frame_type - 251;
298 :
299 102850 : append_frame->locals = DMNEW(verification_type_info_t, number_of_locals);
300 :
301 : /* process all locals */
302 :
303 249775 : for (i = 0; i < number_of_locals; i++)
304 146925 : if (!stackmap_get_verification_type_info(cb, &(append_frame->locals[i])))
305 0 : return false;
306 :
307 102850 : return true;
308 : }
309 :
310 :
311 : /* stackmap_get_full_frame *****************************************************
312 :
313 : full_frame {
314 : u1 frame_type = FULL_FRAME;
315 : u2 offset_delta;
316 : u2 number_of_locals;
317 : verification_type_info locals[number_of_locals];
318 : u2 number_of_stack_items;
319 : verification_type_info stack[number_of_stack_items];
320 : }
321 :
322 : *******************************************************************************/
323 :
324 47063 : static bool stackmap_get_full_frame(ClassBuffer& cb,
325 : stack_map_frame_t *stack_map_frame)
326 : {
327 : full_frame_t *full_frame;
328 : s4 i;
329 :
330 : /* for convenience */
331 :
332 47063 : full_frame = &(stack_map_frame->full_frame);
333 :
334 : /* check buffer size */
335 :
336 47063 : if (!cb.check_size(2 + 2))
337 0 : return false;
338 :
339 : /* get offset delta */
340 :
341 47063 : stack_map_frame->full_frame.offset_delta = cb.read_u2();
342 :
343 : /* get number of locals */
344 :
345 47063 : full_frame->number_of_locals = cb.read_u2();
346 :
347 : /* allocate locals array */
348 :
349 : full_frame->locals =
350 47063 : DMNEW(verification_type_info_t, full_frame->number_of_locals);
351 :
352 : /* process all locals */
353 :
354 278039 : for (i = 0; i < full_frame->number_of_locals; i++)
355 230976 : if (!stackmap_get_verification_type_info(cb, &(full_frame->locals[i])))
356 0 : return false;
357 :
358 : /* get number of stack items */
359 :
360 47063 : if (!cb.check_size(2))
361 0 : return false;
362 :
363 47063 : full_frame->number_of_stack_items = cb.read_u2();
364 :
365 : /* allocate stack array */
366 :
367 : full_frame->stack =
368 47063 : DMNEW(verification_type_info_t, full_frame->number_of_stack_items);
369 :
370 : /* process all stack items */
371 :
372 84278 : for (i = 0; i < full_frame->number_of_stack_items; i++)
373 37215 : if (!stackmap_get_verification_type_info(cb, &(full_frame->stack[i])))
374 0 : return false;
375 :
376 47063 : return true;
377 : }
378 :
379 :
380 : /* stackmap_load_attribute_stackmaptable ***************************************
381 :
382 : stack_map {
383 : u2 attribute_name_index;
384 : u4 attribute_length;
385 : u2 number_of_entries;
386 : stack_map_frame entries[number_of_entries];
387 : }
388 :
389 : union stack_map_frame {
390 : same_frame;
391 : same_locals_1_stack_item_frame;
392 : same_locals_1_stack_item_frame_extended;
393 : chop_frame;
394 : same_frame_extended;
395 : append_frame;
396 : full_frame;
397 : }
398 :
399 : same_frame {
400 : u1 frame_type = SAME; // 0-63
401 : }
402 :
403 : *******************************************************************************/
404 :
405 148188 : bool stackmap_load_attribute_stackmaptable(ClassBuffer& cb, methodinfo *m)
406 : {
407 : classinfo *c;
408 : stack_map_t *stack_map;
409 : s4 i;
410 : u1 frame_type;
411 :
412 : /* get classinfo */
413 :
414 148188 : c = cb.get_class();
415 :
416 : /* allocate stack map structure */
417 :
418 148188 : stack_map = DNEW(stack_map_t);
419 :
420 : STATISTICS(size_stack_map += sizeof(stack_map_t));
421 :
422 : /* check buffer size */
423 :
424 148188 : if (!cb.check_size(4 + 2))
425 0 : return false;
426 :
427 : /* attribute_length */
428 :
429 148188 : stack_map->attribute_length = cb.read_u4();
430 :
431 148188 : if (!cb.check_size(stack_map->attribute_length))
432 0 : return false;
433 :
434 : /* get number of entries */
435 :
436 148188 : stack_map->number_of_entries = cb.read_u2();
437 :
438 : /* process all entries */
439 :
440 148188 : stack_map->entries = DMNEW(stack_map_frame_t, stack_map->number_of_entries);
441 :
442 621797 : for (i = 0; i < stack_map->number_of_entries; i++) {
443 : /* get the frame type */
444 :
445 473609 : frame_type = cb.read_u1();
446 :
447 473609 : stack_map->entries[i].frame_type = frame_type;
448 :
449 : /* process frame */
450 :
451 473609 : if (frame_type <= FRAME_TYPE_SAME) {
452 : /* same_frame */
453 : }
454 211501 : else if (frame_type <= FRAME_TYPE_SAME_LOCALS_1_STACK_ITEM) {
455 : /* same_locals_1_stack_item_frame */
456 :
457 34593 : if (!stackmap_get_same_locals_1_stack_item_frame(cb, &(stack_map->entries[i])))
458 0 : return false;
459 : }
460 176908 : else if (frame_type <= FRAME_TYPE_RESERVED) {
461 : /* reserved */
462 :
463 0 : exceptions_throw_classformaterror(c, "reserved frame type");
464 0 : return false;
465 : }
466 176908 : else if (frame_type == FRAME_TYPE_SAME_LOCALS_1_STACK_ITEM_EXTENDED) {
467 : /* same_locals_1_stack_item_frame_extended */
468 :
469 148 : if (!stackmap_get_same_locals_1_stack_item_frame_extended(cb, &(stack_map->entries[i])))
470 0 : return false;
471 : }
472 176760 : else if (frame_type <= FRAME_TYPE_CHOP) {
473 : /* chop_frame */
474 :
475 25393 : if (!stackmap_get_chop_frame(cb, &(stack_map->entries[i])))
476 0 : return false;
477 : }
478 151367 : else if (frame_type == FRAME_TYPE_SAME_FRAME_EXTENDED) {
479 : /* same_frame_extended */
480 :
481 1454 : if (!stackmap_get_same_frame_extended(cb, &(stack_map->entries[i])))
482 0 : return false;
483 : }
484 149913 : else if (frame_type <= FRAME_TYPE_APPEND) {
485 : /* append_frame */
486 :
487 102850 : if (!stackmap_get_append_frame(cb, &(stack_map->entries[i])))
488 0 : return false;
489 : }
490 47063 : else if (frame_type == FRAME_TYPE_FULL_FRAME) {
491 : /* full_frame */
492 :
493 47063 : if (!stackmap_get_full_frame(cb, &(stack_map->entries[i])))
494 0 : return false;
495 : }
496 : }
497 :
498 : /* store stack map in method structure */
499 :
500 : #if 0
501 : /* currently not used */
502 :
503 : m->stack_map = stack_map;
504 : #endif
505 :
506 148188 : return true;
507 : }
508 :
509 :
510 : /*
511 : * These are local overrides for various environment variables in Emacs.
512 : * Please do not remove this and leave it at the end of the file, where
513 : * Emacs will automagically detect them.
514 : * ---------------------------------------------------------------------
515 : * Local variables:
516 : * mode: c++
517 : * indent-tabs-mode: t
518 : * c-basic-offset: 4
519 : * tab-width: 4
520 : * End:
521 : * vim:noexpandtab:sw=4:ts=4:
522 : */
|