1 /* src/vm/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.hpp"
31 #include "vm/class.hpp"
32 #include "vm/exceptions.hpp"
33 #include "vm/method.hpp"
34 #include "vm/options.h"
35 #include "vm/stackmap.h"
36 #include "vm/statistics.h"
37 #include "vm/suck.hpp"
40 /* stackmap_get_verification_type_info *****************************************
42 union verification_type_info {
44 Integer_variable_info;
49 UninitializedThis_variable_info;
51 Uninitialized_variable_info;
55 u1 tag = ITEM_Top; // 0
58 Integer_variable_info {
59 u1 tag = ITEM_Integer; // 1
63 u1 tag = ITEM_Float; // 2
67 u1 tag = ITEM_Long; // 4
70 Double_variable_info {
71 u1 tag = ITEM_Double; // 3
75 u1 tag = ITEM_Null; // 5
78 UninitializedThis_variable_info {
79 u1 tag = ITEM_UninitializedThis; // 6
82 Object_variable_info {
83 u1 tag = ITEM_Object; // 7
87 Uninitialized_variable_info {
88 u1 tag = ITEM_Uninitialized; // 8
92 *******************************************************************************/
94 static bool stackmap_get_verification_type_info(classbuffer *cb, verification_type_info_t *verification_type_info)
96 /* get verification type */
98 if (!suck_check_classbuffer_size(cb, 1))
101 verification_type_info->tag = suck_u1(cb);
103 /* process the tag */
105 switch (verification_type_info->tag) {
112 case ITEM_UninitializedThis:
116 /* get constant pool index */
118 if (!suck_check_classbuffer_size(cb, 2))
121 verification_type_info->Object_variable_info.cpool_index = suck_u2(cb);
124 case ITEM_Uninitialized:
127 if (!suck_check_classbuffer_size(cb, 2))
130 verification_type_info->Uninitialized_variable_info.offset = suck_u2(cb);
138 /* stackmap_get_same_locals_1_stack_item_frame *********************************
140 same_locals_1_stack_item_frame {
141 u1 frame_type = SAME_LOCALS_1_STACK_ITEM; // 64-127
142 verification_type_info stack[1];
145 *******************************************************************************/
147 static bool stackmap_get_same_locals_1_stack_item_frame(classbuffer *cb, stack_map_frame_t *stack_map_frame)
149 same_locals_1_stack_item_frame_t *same_locals_1_stack_item_frame;
151 /* for convenience */
153 same_locals_1_stack_item_frame =
154 &(stack_map_frame->same_locals_1_stack_item_frame);
156 if (!stackmap_get_verification_type_info(cb, &(same_locals_1_stack_item_frame->stack[0])))
163 /* stackmap_get_same_locals_1_stack_item_frame_extended ************************
165 same_locals_1_stack_item_frame_extended {
166 u1 frame_type = SAME_LOCALS_1_STACK_ITEM_EXTENDED; // 247
168 verification_type_info stack[1];
171 *******************************************************************************/
173 static bool stackmap_get_same_locals_1_stack_item_frame_extended(classbuffer *cb, stack_map_frame_t *stack_map_frame)
175 same_locals_1_stack_item_frame_extended_t *same_locals_1_stack_item_frame_extended;
177 /* for convenience */
179 same_locals_1_stack_item_frame_extended =
180 &(stack_map_frame->same_locals_1_stack_item_frame_extended);
182 /* check buffer size */
184 if (!suck_check_classbuffer_size(cb, 2))
187 /* get offset delta */
189 same_locals_1_stack_item_frame_extended->offset_delta = suck_u2(cb);
193 if (!stackmap_get_verification_type_info(cb, &(same_locals_1_stack_item_frame_extended->stack[0])))
200 /* stackmap_get_chop_frame *****************************************************
203 u1 frame_type = CHOP_FRAME; // 248-250
207 *******************************************************************************/
209 static bool stackmap_get_chop_frame(classbuffer *cb,
210 stack_map_frame_t *stack_map_frame)
212 chop_frame_t *chop_frame;
214 /* for convenience */
216 chop_frame = &(stack_map_frame->chop_frame);
218 /* check buffer size */
220 if (!suck_check_classbuffer_size(cb, 2))
223 /* get offset delta */
225 chop_frame->offset_delta = suck_u2(cb);
231 /* stackmap_get_same_frame_extended ********************************************
233 same_frame_extended {
234 u1 frame_type = SAME_FRAME_EXTENDED; // 251
238 *******************************************************************************/
240 static bool stackmap_get_same_frame_extended(classbuffer *cb,
241 stack_map_frame_t *stack_map_frame)
243 same_frame_extended_t *same_frame_extended;
245 /* for convenience */
247 same_frame_extended = &(stack_map_frame->same_frame_extended);
249 /* check buffer size */
251 if (!suck_check_classbuffer_size(cb, 2))
254 /* get offset delta */
256 same_frame_extended->offset_delta = suck_u2(cb);
262 /* stackmap_get_append_frame ***************************************************
265 u1 frame_type = APPEND_FRAME; // 252-254
267 verification_type_info locals[frame_Type - 251];
270 *******************************************************************************/
272 static bool stackmap_get_append_frame(classbuffer *cb,
273 stack_map_frame_t *stack_map_frame)
275 append_frame_t *append_frame;
279 /* for convenience */
281 append_frame = &(stack_map_frame->append_frame);
283 /* check buffer size */
285 if (!suck_check_classbuffer_size(cb, 2))
288 /* get offset delta */
290 append_frame->offset_delta = suck_u2(cb);
292 /* allocate locals array */
294 number_of_locals = append_frame->frame_type - 251;
296 append_frame->locals = DMNEW(verification_type_info_t, number_of_locals);
298 /* process all locals */
300 for (i = 0; i < number_of_locals; i++)
301 if (!stackmap_get_verification_type_info(cb, &(append_frame->locals[i])))
308 /* stackmap_get_full_frame *****************************************************
311 u1 frame_type = FULL_FRAME;
314 verification_type_info locals[number_of_locals];
315 u2 number_of_stack_items;
316 verification_type_info stack[number_of_stack_items];
319 *******************************************************************************/
321 static bool stackmap_get_full_frame(classbuffer *cb,
322 stack_map_frame_t *stack_map_frame)
324 full_frame_t *full_frame;
327 /* for convenience */
329 full_frame = &(stack_map_frame->full_frame);
331 /* check buffer size */
333 if (!suck_check_classbuffer_size(cb, 2 + 2))
336 /* get offset delta */
338 stack_map_frame->full_frame.offset_delta = suck_u2(cb);
340 /* get number of locals */
342 full_frame->number_of_locals = suck_u2(cb);
344 /* allocate locals array */
347 DMNEW(verification_type_info_t, full_frame->number_of_locals);
349 /* process all locals */
351 for (i = 0; i < full_frame->number_of_locals; i++)
352 if (!stackmap_get_verification_type_info(cb, &(full_frame->locals[i])))
355 /* get number of stack items */
357 if (!suck_check_classbuffer_size(cb, 2))
360 full_frame->number_of_stack_items = suck_u2(cb);
362 /* allocate stack array */
365 DMNEW(verification_type_info_t, full_frame->number_of_stack_items);
367 /* process all stack items */
369 for (i = 0; i < full_frame->number_of_stack_items; i++)
370 if (!stackmap_get_verification_type_info(cb, &(full_frame->stack[i])))
377 /* stackmap_load_attribute_stackmaptable ***************************************
380 u2 attribute_name_index;
382 u2 number_of_entries;
383 stack_map_frame entries[number_of_entries];
386 union stack_map_frame {
388 same_locals_1_stack_item_frame;
389 same_locals_1_stack_item_frame_extended;
397 u1 frame_type = SAME; // 0-63
400 *******************************************************************************/
402 bool stackmap_load_attribute_stackmaptable(classbuffer *cb, methodinfo *m)
405 stack_map_t *stack_map;
413 /* allocate stack map structure */
415 stack_map = DNEW(stack_map_t);
417 STATISTICS(size_stack_map += sizeof(stack_map_t));
419 /* check buffer size */
421 if (!suck_check_classbuffer_size(cb, 4 + 2))
424 /* attribute_length */
426 stack_map->attribute_length = suck_u4(cb);
428 if (!suck_check_classbuffer_size(cb, stack_map->attribute_length))
431 /* get number of entries */
433 stack_map->number_of_entries = suck_u2(cb);
435 /* process all entries */
437 stack_map->entries = DMNEW(stack_map_frame_t, stack_map->number_of_entries);
439 for (i = 0; i < stack_map->number_of_entries; i++) {
440 /* get the frame type */
442 frame_type = suck_u1(cb);
444 stack_map->entries[i].frame_type = frame_type;
448 if (frame_type <= FRAME_TYPE_SAME) {
451 else if (frame_type <= FRAME_TYPE_SAME_LOCALS_1_STACK_ITEM) {
452 /* same_locals_1_stack_item_frame */
454 if (!stackmap_get_same_locals_1_stack_item_frame(cb, &(stack_map->entries[i])))
457 else if (frame_type <= FRAME_TYPE_RESERVED) {
460 exceptions_throw_classformaterror(c, "reserved frame type");
463 else if (frame_type == FRAME_TYPE_SAME_LOCALS_1_STACK_ITEM_EXTENDED) {
464 /* same_locals_1_stack_item_frame_extended */
466 if (!stackmap_get_same_locals_1_stack_item_frame_extended(cb, &(stack_map->entries[i])))
469 else if (frame_type <= FRAME_TYPE_CHOP) {
472 if (!stackmap_get_chop_frame(cb, &(stack_map->entries[i])))
475 else if (frame_type == FRAME_TYPE_SAME_FRAME_EXTENDED) {
476 /* same_frame_extended */
478 if (!stackmap_get_same_frame_extended(cb, &(stack_map->entries[i])))
481 else if (frame_type <= FRAME_TYPE_APPEND) {
484 if (!stackmap_get_append_frame(cb, &(stack_map->entries[i])))
487 else if (frame_type == FRAME_TYPE_FULL_FRAME) {
490 if (!stackmap_get_full_frame(cb, &(stack_map->entries[i])))
495 /* store stack map in method structure */
498 /* currently not used */
500 m->stack_map = stack_map;
508 * These are local overrides for various environment variables in Emacs.
509 * Please do not remove this and leave it at the end of the file, where
510 * Emacs will automagically detect them.
511 * ---------------------------------------------------------------------
514 * indent-tabs-mode: t
518 * vim:noexpandtab:sw=4:ts=4: