1 /* src/vmcore/stackmap.c - class attribute StackMapTable
3 Copyright (C) 2006, 2007, 2008
4 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
6 This file is part of CACAO.
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.
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.
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
29 #include "mm/memory.h"
31 #include "vm/exceptions.hpp"
33 #include "vmcore/class.h"
34 #include "vmcore/method.h"
35 #include "vmcore/options.h"
36 #include "vmcore/stackmap.h"
37 #include "vmcore/statistics.h"
38 #include "vmcore/suck.h"
41 /* stackmap_get_verification_type_info *****************************************
43 union verification_type_info {
45 Integer_variable_info;
50 UninitializedThis_variable_info;
52 Uninitialized_variable_info;
56 u1 tag = ITEM_Top; // 0
59 Integer_variable_info {
60 u1 tag = ITEM_Integer; // 1
64 u1 tag = ITEM_Float; // 2
68 u1 tag = ITEM_Long; // 4
71 Double_variable_info {
72 u1 tag = ITEM_Double; // 3
76 u1 tag = ITEM_Null; // 5
79 UninitializedThis_variable_info {
80 u1 tag = ITEM_UninitializedThis; // 6
83 Object_variable_info {
84 u1 tag = ITEM_Object; // 7
88 Uninitialized_variable_info {
89 u1 tag = ITEM_Uninitialized; // 8
93 *******************************************************************************/
95 static bool stackmap_get_verification_type_info(classbuffer *cb, verification_type_info_t *verification_type_info)
97 /* get verification type */
99 if (!suck_check_classbuffer_size(cb, 1))
102 verification_type_info->tag = suck_u1(cb);
104 /* process the tag */
106 switch (verification_type_info->tag) {
113 case ITEM_UninitializedThis:
117 /* get constant pool index */
119 if (!suck_check_classbuffer_size(cb, 2))
122 verification_type_info->Object_variable_info.cpool_index = suck_u2(cb);
125 case ITEM_Uninitialized:
128 if (!suck_check_classbuffer_size(cb, 2))
131 verification_type_info->Uninitialized_variable_info.offset = suck_u2(cb);
139 /* stackmap_get_same_locals_1_stack_item_frame *********************************
141 same_locals_1_stack_item_frame {
142 u1 frame_type = SAME_LOCALS_1_STACK_ITEM; // 64-127
143 verification_type_info stack[1];
146 *******************************************************************************/
148 static bool stackmap_get_same_locals_1_stack_item_frame(classbuffer *cb, stack_map_frame_t *stack_map_frame)
150 same_locals_1_stack_item_frame_t *same_locals_1_stack_item_frame;
152 /* for convenience */
154 same_locals_1_stack_item_frame =
155 &(stack_map_frame->same_locals_1_stack_item_frame);
157 if (!stackmap_get_verification_type_info(cb, &(same_locals_1_stack_item_frame->stack[0])))
164 /* stackmap_get_same_locals_1_stack_item_frame_extended ************************
166 same_locals_1_stack_item_frame_extended {
167 u1 frame_type = SAME_LOCALS_1_STACK_ITEM_EXTENDED; // 247
169 verification_type_info stack[1];
172 *******************************************************************************/
174 static bool stackmap_get_same_locals_1_stack_item_frame_extended(classbuffer *cb, stack_map_frame_t *stack_map_frame)
176 same_locals_1_stack_item_frame_extended_t *same_locals_1_stack_item_frame_extended;
178 /* for convenience */
180 same_locals_1_stack_item_frame_extended =
181 &(stack_map_frame->same_locals_1_stack_item_frame_extended);
183 /* check buffer size */
185 if (!suck_check_classbuffer_size(cb, 2))
188 /* get offset delta */
190 same_locals_1_stack_item_frame_extended->offset_delta = suck_u2(cb);
194 if (!stackmap_get_verification_type_info(cb, &(same_locals_1_stack_item_frame_extended->stack[0])))
201 /* stackmap_get_chop_frame *****************************************************
204 u1 frame_type = CHOP_FRAME; // 248-250
208 *******************************************************************************/
210 static bool stackmap_get_chop_frame(classbuffer *cb,
211 stack_map_frame_t *stack_map_frame)
213 chop_frame_t *chop_frame;
215 /* for convenience */
217 chop_frame = &(stack_map_frame->chop_frame);
219 /* check buffer size */
221 if (!suck_check_classbuffer_size(cb, 2))
224 /* get offset delta */
226 chop_frame->offset_delta = suck_u2(cb);
232 /* stackmap_get_same_frame_extended ********************************************
234 same_frame_extended {
235 u1 frame_type = SAME_FRAME_EXTENDED; // 251
239 *******************************************************************************/
241 static bool stackmap_get_same_frame_extended(classbuffer *cb,
242 stack_map_frame_t *stack_map_frame)
244 same_frame_extended_t *same_frame_extended;
246 /* for convenience */
248 same_frame_extended = &(stack_map_frame->same_frame_extended);
250 /* check buffer size */
252 if (!suck_check_classbuffer_size(cb, 2))
255 /* get offset delta */
257 same_frame_extended->offset_delta = suck_u2(cb);
263 /* stackmap_get_append_frame ***************************************************
266 u1 frame_type = APPEND_FRAME; // 252-254
268 verification_type_info locals[frame_Type - 251];
271 *******************************************************************************/
273 static bool stackmap_get_append_frame(classbuffer *cb,
274 stack_map_frame_t *stack_map_frame)
276 append_frame_t *append_frame;
280 /* for convenience */
282 append_frame = &(stack_map_frame->append_frame);
284 /* check buffer size */
286 if (!suck_check_classbuffer_size(cb, 2))
289 /* get offset delta */
291 append_frame->offset_delta = suck_u2(cb);
293 /* allocate locals array */
295 number_of_locals = append_frame->frame_type - 251;
297 append_frame->locals = DMNEW(verification_type_info_t, number_of_locals);
299 /* process all locals */
301 for (i = 0; i < number_of_locals; i++)
302 if (!stackmap_get_verification_type_info(cb, &(append_frame->locals[i])))
309 /* stackmap_get_full_frame *****************************************************
312 u1 frame_type = FULL_FRAME;
315 verification_type_info locals[number_of_locals];
316 u2 number_of_stack_items;
317 verification_type_info stack[number_of_stack_items];
320 *******************************************************************************/
322 static bool stackmap_get_full_frame(classbuffer *cb,
323 stack_map_frame_t *stack_map_frame)
325 full_frame_t *full_frame;
328 /* for convenience */
330 full_frame = &(stack_map_frame->full_frame);
332 /* check buffer size */
334 if (!suck_check_classbuffer_size(cb, 2 + 2))
337 /* get offset delta */
339 stack_map_frame->full_frame.offset_delta = suck_u2(cb);
341 /* get number of locals */
343 full_frame->number_of_locals = suck_u2(cb);
345 /* allocate locals array */
348 DMNEW(verification_type_info_t, full_frame->number_of_locals);
350 /* process all locals */
352 for (i = 0; i < full_frame->number_of_locals; i++)
353 if (!stackmap_get_verification_type_info(cb, &(full_frame->locals[i])))
356 /* get number of stack items */
358 if (!suck_check_classbuffer_size(cb, 2))
361 full_frame->number_of_stack_items = suck_u2(cb);
363 /* allocate stack array */
366 DMNEW(verification_type_info_t, full_frame->number_of_stack_items);
368 /* process all stack items */
370 for (i = 0; i < full_frame->number_of_stack_items; i++)
371 if (!stackmap_get_verification_type_info(cb, &(full_frame->stack[i])))
378 /* stackmap_load_attribute_stackmaptable ***************************************
381 u2 attribute_name_index;
383 u2 number_of_entries;
384 stack_map_frame entries[number_of_entries];
387 union stack_map_frame {
389 same_locals_1_stack_item_frame;
390 same_locals_1_stack_item_frame_extended;
398 u1 frame_type = SAME; // 0-63
401 *******************************************************************************/
403 bool stackmap_load_attribute_stackmaptable(classbuffer *cb, methodinfo *m)
406 stack_map_t *stack_map;
414 /* allocate stack map structure */
416 stack_map = DNEW(stack_map_t);
418 STATISTICS(size_stack_map += sizeof(stack_map_t));
420 /* check buffer size */
422 if (!suck_check_classbuffer_size(cb, 4 + 2))
425 /* attribute_length */
427 stack_map->attribute_length = suck_u4(cb);
429 if (!suck_check_classbuffer_size(cb, stack_map->attribute_length))
432 /* get number of entries */
434 stack_map->number_of_entries = suck_u2(cb);
436 /* process all entries */
438 stack_map->entries = DMNEW(stack_map_frame_t, stack_map->number_of_entries);
440 for (i = 0; i < stack_map->number_of_entries; i++) {
441 /* get the frame type */
443 frame_type = suck_u1(cb);
445 stack_map->entries[i].frame_type = frame_type;
449 if (frame_type <= FRAME_TYPE_SAME) {
452 else if (frame_type <= FRAME_TYPE_SAME_LOCALS_1_STACK_ITEM) {
453 /* same_locals_1_stack_item_frame */
455 if (!stackmap_get_same_locals_1_stack_item_frame(cb, &(stack_map->entries[i])))
458 else if (frame_type <= FRAME_TYPE_RESERVED) {
461 exceptions_throw_classformaterror(c, "reserved frame type");
464 else if (frame_type == FRAME_TYPE_SAME_LOCALS_1_STACK_ITEM_EXTENDED) {
465 /* same_locals_1_stack_item_frame_extended */
467 if (!stackmap_get_same_locals_1_stack_item_frame_extended(cb, &(stack_map->entries[i])))
470 else if (frame_type <= FRAME_TYPE_CHOP) {
473 if (!stackmap_get_chop_frame(cb, &(stack_map->entries[i])))
476 else if (frame_type == FRAME_TYPE_SAME_FRAME_EXTENDED) {
477 /* same_frame_extended */
479 if (!stackmap_get_same_frame_extended(cb, &(stack_map->entries[i])))
482 else if (frame_type <= FRAME_TYPE_APPEND) {
485 if (!stackmap_get_append_frame(cb, &(stack_map->entries[i])))
488 else if (frame_type == FRAME_TYPE_FULL_FRAME) {
491 if (!stackmap_get_full_frame(cb, &(stack_map->entries[i])))
496 /* store stack map in method structure */
499 /* currently not used */
501 m->stack_map = stack_map;
509 * These are local overrides for various environment variables in Emacs.
510 * Please do not remove this and leave it at the end of the file, where
511 * Emacs will automagically detect them.
512 * ---------------------------------------------------------------------
515 * indent-tabs-mode: t
519 * vim:noexpandtab:sw=4:ts=4: