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