* Removed all Id tags.
[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 */
26
27
28 #include "config.h"
29 #include "vm/types.h"
30
31 #include "mm/memory.h"
32
33 #include "vm/exceptions.h"
34
35 #include "vmcore/class.h"
36 #include "vmcore/method.h"
37 #include "vmcore/options.h"
38 #include "vmcore/stackmap.h"
39 #include "vmcore/statistics.h"
40 #include "vmcore/suck.h"
41
42
43 /* stackmap_get_verification_type_info *****************************************
44
45    union verification_type_info {
46        Top_variable_info;
47            Integer_variable_info;
48            Float_variable_info;
49            Long_variable_info;
50            Double_variable_info;
51            Null_variable_info;
52            UninitializedThis_variable_info;
53            Object_variable_info;
54            Uninitialized_variable_info;
55    }
56
57    Top_variable_info {
58        u1 tag = ITEM_Top;  // 0
59    }
60
61    Integer_variable_info {
62        u1 tag = ITEM_Integer;  // 1
63    }
64
65    Float_variable_info {
66        u1 tag = ITEM_Float;  // 2
67    }
68
69    Long_variable_info {
70        u1 tag = ITEM_Long;  // 4
71    }
72
73    Double_variable_info {
74        u1 tag = ITEM_Double;  // 3
75    }
76
77    Null_variable_info {
78        u1 tag = ITEM_Null;  // 5
79    }
80
81    UninitializedThis_variable_info {
82        u1 tag = ITEM_UninitializedThis;  // 6
83    }
84
85    Object_variable_info {
86        u1 tag = ITEM_Object;  // 7
87            u2 cpool_index;
88    }
89
90    Uninitialized_variable_info {
91        u1 tag = ITEM_Uninitialized;  // 8
92            u2 offset;
93    }
94
95 *******************************************************************************/
96
97 static bool stackmap_get_verification_type_info(classbuffer *cb, verification_type_info_t *verification_type_info)
98 {
99         /* get verification type */
100
101         if (!suck_check_classbuffer_size(cb, 1))
102                 return false;
103
104         verification_type_info->tag = suck_u1(cb);
105
106         /* process the tag */
107
108         switch (verification_type_info->tag) {
109         case ITEM_Top:
110         case ITEM_Integer:
111         case ITEM_Float:
112         case ITEM_Long:
113         case ITEM_Double:
114         case ITEM_Null:
115         case ITEM_UninitializedThis:
116                 break;
117
118         case ITEM_Object:
119                 /* get constant pool index */
120
121                 if (!suck_check_classbuffer_size(cb, 2))
122                         return false;
123
124                 verification_type_info->Object_variable_info.cpool_index = suck_u2(cb);
125                 break;
126
127         case ITEM_Uninitialized:
128                 /* get offset */
129
130                 if (!suck_check_classbuffer_size(cb, 2))
131                         return false;
132
133                 verification_type_info->Uninitialized_variable_info.offset = suck_u2(cb);
134                 break;
135         }
136
137         return true;
138 }
139
140
141 /* stackmap_get_same_locals_1_stack_item_frame *********************************
142
143    same_locals_1_stack_item_frame {
144        u1 frame_type = SAME_LOCALS_1_STACK_ITEM;  // 64-127
145            verification_type_info stack[1];
146    }
147
148 *******************************************************************************/
149
150 static bool stackmap_get_same_locals_1_stack_item_frame(classbuffer *cb, stack_map_frame_t *stack_map_frame)
151 {
152         same_locals_1_stack_item_frame_t *same_locals_1_stack_item_frame;
153
154         /* for convenience */
155
156         same_locals_1_stack_item_frame =
157                 &(stack_map_frame->same_locals_1_stack_item_frame);
158
159         if (!stackmap_get_verification_type_info(cb, &(same_locals_1_stack_item_frame->stack[0])))
160                 return false;
161
162         return true;
163 }
164
165
166 /* stackmap_get_same_locals_1_stack_item_frame_extended ************************
167
168    same_locals_1_stack_item_frame_extended {
169        u1 frame_type = SAME_LOCALS_1_STACK_ITEM_EXTENDED;  // 247
170            u2 offset_delta;
171            verification_type_info stack[1];
172    }
173
174 *******************************************************************************/
175
176 static bool stackmap_get_same_locals_1_stack_item_frame_extended(classbuffer *cb, stack_map_frame_t *stack_map_frame)
177 {
178         same_locals_1_stack_item_frame_extended_t *same_locals_1_stack_item_frame_extended;
179
180         /* for convenience */
181
182         same_locals_1_stack_item_frame_extended =
183                 &(stack_map_frame->same_locals_1_stack_item_frame_extended);
184
185         /* check buffer size */
186
187         if (!suck_check_classbuffer_size(cb, 2))
188                 return false;
189
190         /* get offset delta */
191
192         same_locals_1_stack_item_frame_extended->offset_delta = suck_u2(cb);
193
194         /* process stack */
195
196         if (!stackmap_get_verification_type_info(cb, &(same_locals_1_stack_item_frame_extended->stack[0])))
197                 return false;
198
199         return true;
200 }
201
202
203 /* stackmap_get_chop_frame *****************************************************
204
205    chop_frame {
206        u1 frame_type = CHOP_FRAME;  // 248-250
207            u2 offset_delta;
208    }
209
210 *******************************************************************************/
211
212 static bool stackmap_get_chop_frame(classbuffer *cb,
213                                                                         stack_map_frame_t *stack_map_frame)
214 {
215         chop_frame_t *chop_frame;
216
217         /* for convenience */
218
219         chop_frame = &(stack_map_frame->chop_frame);
220
221         /* check buffer size */
222
223         if (!suck_check_classbuffer_size(cb, 2))
224                 return false;
225
226         /* get offset delta */
227
228         chop_frame->offset_delta = suck_u2(cb);
229
230         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 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         same_frame_extended = &(stack_map_frame->same_frame_extended);
251
252         /* check buffer size */
253
254         if (!suck_check_classbuffer_size(cb, 2))
255                 return false;
256
257         /* get offset delta */
258
259         same_frame_extended->offset_delta = suck_u2(cb);
260
261         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 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         append_frame = &(stack_map_frame->append_frame);
285
286         /* check buffer size */
287
288         if (!suck_check_classbuffer_size(cb, 2))
289                 return false;
290
291         /* get offset delta */
292
293         append_frame->offset_delta = suck_u2(cb);
294
295         /* allocate locals array */
296
297         number_of_locals = append_frame->frame_type - 251;
298
299         append_frame->locals = DMNEW(verification_type_info_t, number_of_locals);
300
301         /* process all locals */
302
303         for (i = 0; i < number_of_locals; i++)
304                 if (!stackmap_get_verification_type_info(cb, &(append_frame->locals[i])))
305                         return false;
306
307         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 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         full_frame = &(stack_map_frame->full_frame);
333
334         /* check buffer size */
335
336         if (!suck_check_classbuffer_size(cb, 2 + 2))
337                 return false;
338
339         /*  get offset delta */
340
341         stack_map_frame->full_frame.offset_delta = suck_u2(cb);
342
343         /* get number of locals */
344
345         full_frame->number_of_locals = suck_u2(cb);
346
347         /* allocate locals array */
348
349         full_frame->locals =
350                 DMNEW(verification_type_info_t, full_frame->number_of_locals);
351
352         /* process all locals */
353
354         for (i = 0; i < full_frame->number_of_locals; i++)
355                 if (!stackmap_get_verification_type_info(cb, &(full_frame->locals[i])))
356                         return false;
357
358         /* get number of stack items */
359
360         if (!suck_check_classbuffer_size(cb, 2))
361                 return false;
362
363         full_frame->number_of_stack_items = suck_u2(cb);
364
365         /* allocate stack array */
366
367         full_frame->stack =
368                 DMNEW(verification_type_info_t, full_frame->number_of_stack_items);
369
370         /* process all stack items */
371
372         for (i = 0; i < full_frame->number_of_stack_items; i++)
373                 if (!stackmap_get_verification_type_info(cb, &(full_frame->stack[i])))
374                         return false;
375
376         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 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         c = cb->class;
415
416         /* allocate stack map structure */
417
418         stack_map = DNEW(stack_map_t);
419
420         STATISTICS(size_stack_map += sizeof(stack_map_t));
421
422         /* check buffer size */
423
424         if (!suck_check_classbuffer_size(cb, 4 + 2))
425                 return false;
426
427         /* attribute_length */
428
429         stack_map->attribute_length = suck_u4(cb);
430
431         if (!suck_check_classbuffer_size(cb, stack_map->attribute_length))
432                 return false;
433
434         /* get number of entries */
435
436         stack_map->number_of_entries = suck_u2(cb);
437
438         /* process all entries */
439
440         stack_map->entries = DMNEW(stack_map_frame_t, stack_map->number_of_entries);
441
442         for (i = 0; i < stack_map->number_of_entries; i++) {
443                 /* get the frame type */
444
445                 frame_type = suck_u1(cb);
446
447                 stack_map->entries[i].frame_type = frame_type;
448
449                 /* process frame */
450
451                 if (frame_type <= FRAME_TYPE_SAME) {
452                         /* same_frame */
453                 }
454                 else if (frame_type <= FRAME_TYPE_SAME_LOCALS_1_STACK_ITEM) {
455                         /* same_locals_1_stack_item_frame */
456
457                         if (!stackmap_get_same_locals_1_stack_item_frame(cb, &(stack_map->entries[i])))
458                                 return false;
459                 }
460                 else if (frame_type <= FRAME_TYPE_RESERVED) {
461                         /* reserved */
462
463                         exceptions_throw_classformaterror(c, "reserved frame type");
464                         return false;
465                 }
466                 else if (frame_type == FRAME_TYPE_SAME_LOCALS_1_STACK_ITEM_EXTENDED) {
467                         /* same_locals_1_stack_item_frame_extended */
468
469                         if (!stackmap_get_same_locals_1_stack_item_frame_extended(cb, &(stack_map->entries[i])))
470                                 return false;
471                 }
472                 else if (frame_type <= FRAME_TYPE_CHOP) {
473                         /* chop_frame */
474
475                         if (!stackmap_get_chop_frame(cb, &(stack_map->entries[i])))
476                                 return false;
477                 }
478                 else if (frame_type == FRAME_TYPE_SAME_FRAME_EXTENDED) {
479                         /* same_frame_extended */
480
481                         if (!stackmap_get_same_frame_extended(cb, &(stack_map->entries[i])))
482                                 return false;
483                 }
484                 else if (frame_type <= FRAME_TYPE_APPEND) {
485                         /* append_frame */
486
487                         if (!stackmap_get_append_frame(cb, &(stack_map->entries[i])))
488                                 return false;
489                 }
490                 else if (frame_type == FRAME_TYPE_FULL_FRAME) {
491                         /* full_frame */
492
493                         if (!stackmap_get_full_frame(cb, &(stack_map->entries[i])))
494                                 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         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  */