34ea56baace15f40311ee4ff5fb6e7111e3a4319
[cacao.git] / src / vmcore / stackmap.c
1 /* src/vmcore/stackmap.c - class attribute StackMapTable
2
3    Copyright (C) 2006, 2007, 2008
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.h"
28
29 #include "mm/memory.h"
30
31 #include "vm/exceptions.hpp"
32
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"
39
40
41 /* stackmap_get_verification_type_info *****************************************
42
43    union verification_type_info {
44        Top_variable_info;
45            Integer_variable_info;
46            Float_variable_info;
47            Long_variable_info;
48            Double_variable_info;
49            Null_variable_info;
50            UninitializedThis_variable_info;
51            Object_variable_info;
52            Uninitialized_variable_info;
53    }
54
55    Top_variable_info {
56        u1 tag = ITEM_Top;  // 0
57    }
58
59    Integer_variable_info {
60        u1 tag = ITEM_Integer;  // 1
61    }
62
63    Float_variable_info {
64        u1 tag = ITEM_Float;  // 2
65    }
66
67    Long_variable_info {
68        u1 tag = ITEM_Long;  // 4
69    }
70
71    Double_variable_info {
72        u1 tag = ITEM_Double;  // 3
73    }
74
75    Null_variable_info {
76        u1 tag = ITEM_Null;  // 5
77    }
78
79    UninitializedThis_variable_info {
80        u1 tag = ITEM_UninitializedThis;  // 6
81    }
82
83    Object_variable_info {
84        u1 tag = ITEM_Object;  // 7
85            u2 cpool_index;
86    }
87
88    Uninitialized_variable_info {
89        u1 tag = ITEM_Uninitialized;  // 8
90            u2 offset;
91    }
92
93 *******************************************************************************/
94
95 static bool stackmap_get_verification_type_info(classbuffer *cb, verification_type_info_t *verification_type_info)
96 {
97         /* get verification type */
98
99         if (!suck_check_classbuffer_size(cb, 1))
100                 return false;
101
102         verification_type_info->tag = suck_u1(cb);
103
104         /* process the tag */
105
106         switch (verification_type_info->tag) {
107         case ITEM_Top:
108         case ITEM_Integer:
109         case ITEM_Float:
110         case ITEM_Long:
111         case ITEM_Double:
112         case ITEM_Null:
113         case ITEM_UninitializedThis:
114                 break;
115
116         case ITEM_Object:
117                 /* get constant pool index */
118
119                 if (!suck_check_classbuffer_size(cb, 2))
120                         return false;
121
122                 verification_type_info->Object_variable_info.cpool_index = suck_u2(cb);
123                 break;
124
125         case ITEM_Uninitialized:
126                 /* get offset */
127
128                 if (!suck_check_classbuffer_size(cb, 2))
129                         return false;
130
131                 verification_type_info->Uninitialized_variable_info.offset = suck_u2(cb);
132                 break;
133         }
134
135         return true;
136 }
137
138
139 /* stackmap_get_same_locals_1_stack_item_frame *********************************
140
141    same_locals_1_stack_item_frame {
142        u1 frame_type = SAME_LOCALS_1_STACK_ITEM;  // 64-127
143            verification_type_info stack[1];
144    }
145
146 *******************************************************************************/
147
148 static bool stackmap_get_same_locals_1_stack_item_frame(classbuffer *cb, stack_map_frame_t *stack_map_frame)
149 {
150         same_locals_1_stack_item_frame_t *same_locals_1_stack_item_frame;
151
152         /* for convenience */
153
154         same_locals_1_stack_item_frame =
155                 &(stack_map_frame->same_locals_1_stack_item_frame);
156
157         if (!stackmap_get_verification_type_info(cb, &(same_locals_1_stack_item_frame->stack[0])))
158                 return false;
159
160         return true;
161 }
162
163
164 /* stackmap_get_same_locals_1_stack_item_frame_extended ************************
165
166    same_locals_1_stack_item_frame_extended {
167        u1 frame_type = SAME_LOCALS_1_STACK_ITEM_EXTENDED;  // 247
168            u2 offset_delta;
169            verification_type_info stack[1];
170    }
171
172 *******************************************************************************/
173
174 static bool stackmap_get_same_locals_1_stack_item_frame_extended(classbuffer *cb, stack_map_frame_t *stack_map_frame)
175 {
176         same_locals_1_stack_item_frame_extended_t *same_locals_1_stack_item_frame_extended;
177
178         /* for convenience */
179
180         same_locals_1_stack_item_frame_extended =
181                 &(stack_map_frame->same_locals_1_stack_item_frame_extended);
182
183         /* check buffer size */
184
185         if (!suck_check_classbuffer_size(cb, 2))
186                 return false;
187
188         /* get offset delta */
189
190         same_locals_1_stack_item_frame_extended->offset_delta = suck_u2(cb);
191
192         /* process stack */
193
194         if (!stackmap_get_verification_type_info(cb, &(same_locals_1_stack_item_frame_extended->stack[0])))
195                 return false;
196
197         return true;
198 }
199
200
201 /* stackmap_get_chop_frame *****************************************************
202
203    chop_frame {
204        u1 frame_type = CHOP_FRAME;  // 248-250
205            u2 offset_delta;
206    }
207
208 *******************************************************************************/
209
210 static bool stackmap_get_chop_frame(classbuffer *cb,
211                                                                         stack_map_frame_t *stack_map_frame)
212 {
213         chop_frame_t *chop_frame;
214
215         /* for convenience */
216
217         chop_frame = &(stack_map_frame->chop_frame);
218
219         /* check buffer size */
220
221         if (!suck_check_classbuffer_size(cb, 2))
222                 return false;
223
224         /* get offset delta */
225
226         chop_frame->offset_delta = suck_u2(cb);
227
228         return true;
229 }
230
231
232 /* stackmap_get_same_frame_extended ********************************************
233
234    same_frame_extended {
235        u1 frame_type = SAME_FRAME_EXTENDED;  // 251
236            u2 offset_delta;
237    }
238
239 *******************************************************************************/
240
241 static bool stackmap_get_same_frame_extended(classbuffer *cb,
242                                                                                          stack_map_frame_t *stack_map_frame)
243 {
244         same_frame_extended_t *same_frame_extended;
245
246         /* for convenience */
247
248         same_frame_extended = &(stack_map_frame->same_frame_extended);
249
250         /* check buffer size */
251
252         if (!suck_check_classbuffer_size(cb, 2))
253                 return false;
254
255         /* get offset delta */
256
257         same_frame_extended->offset_delta = suck_u2(cb);
258
259         return true;
260 }
261
262
263 /* stackmap_get_append_frame ***************************************************
264
265    append_frame {
266        u1 frame_type = APPEND_FRAME;  // 252-254
267            u2 offset_delta;
268            verification_type_info locals[frame_Type - 251];
269    }
270
271 *******************************************************************************/
272
273 static bool stackmap_get_append_frame(classbuffer *cb,
274                                                                           stack_map_frame_t *stack_map_frame)
275 {
276         append_frame_t *append_frame;
277         s4              number_of_locals;
278         s4              i;
279
280         /* for convenience */
281
282         append_frame = &(stack_map_frame->append_frame);
283
284         /* check buffer size */
285
286         if (!suck_check_classbuffer_size(cb, 2))
287                 return false;
288
289         /* get offset delta */
290
291         append_frame->offset_delta = suck_u2(cb);
292
293         /* allocate locals array */
294
295         number_of_locals = append_frame->frame_type - 251;
296
297         append_frame->locals = DMNEW(verification_type_info_t, number_of_locals);
298
299         /* process all locals */
300
301         for (i = 0; i < number_of_locals; i++)
302                 if (!stackmap_get_verification_type_info(cb, &(append_frame->locals[i])))
303                         return false;
304
305         return true;
306 }
307
308
309 /* stackmap_get_full_frame *****************************************************
310
311    full_frame {
312        u1 frame_type = FULL_FRAME;
313            u2 offset_delta;
314            u2 number_of_locals;
315            verification_type_info locals[number_of_locals];
316            u2 number_of_stack_items;
317            verification_type_info stack[number_of_stack_items];
318    }
319
320 *******************************************************************************/
321
322 static bool stackmap_get_full_frame(classbuffer *cb,
323                                                                         stack_map_frame_t *stack_map_frame)
324 {
325         full_frame_t *full_frame;
326         s4 i;
327
328         /* for convenience */
329
330         full_frame = &(stack_map_frame->full_frame);
331
332         /* check buffer size */
333
334         if (!suck_check_classbuffer_size(cb, 2 + 2))
335                 return false;
336
337         /*  get offset delta */
338
339         stack_map_frame->full_frame.offset_delta = suck_u2(cb);
340
341         /* get number of locals */
342
343         full_frame->number_of_locals = suck_u2(cb);
344
345         /* allocate locals array */
346
347         full_frame->locals =
348                 DMNEW(verification_type_info_t, full_frame->number_of_locals);
349
350         /* process all locals */
351
352         for (i = 0; i < full_frame->number_of_locals; i++)
353                 if (!stackmap_get_verification_type_info(cb, &(full_frame->locals[i])))
354                         return false;
355
356         /* get number of stack items */
357
358         if (!suck_check_classbuffer_size(cb, 2))
359                 return false;
360
361         full_frame->number_of_stack_items = suck_u2(cb);
362
363         /* allocate stack array */
364
365         full_frame->stack =
366                 DMNEW(verification_type_info_t, full_frame->number_of_stack_items);
367
368         /* process all stack items */
369
370         for (i = 0; i < full_frame->number_of_stack_items; i++)
371                 if (!stackmap_get_verification_type_info(cb, &(full_frame->stack[i])))
372                         return false;
373
374         return true;
375 }
376
377
378 /* stackmap_load_attribute_stackmaptable ***************************************
379
380    stack_map {
381            u2 attribute_name_index;
382            u4 attribute_length;
383            u2 number_of_entries;
384            stack_map_frame entries[number_of_entries];
385    }
386
387    union stack_map_frame {
388        same_frame;
389            same_locals_1_stack_item_frame;
390            same_locals_1_stack_item_frame_extended;
391            chop_frame;
392            same_frame_extended;
393            append_frame;
394            full_frame;
395    }
396
397    same_frame {
398        u1 frame_type = SAME;  // 0-63
399    }
400
401 *******************************************************************************/
402
403 bool stackmap_load_attribute_stackmaptable(classbuffer *cb, methodinfo *m)
404 {
405         classinfo       *c;
406         stack_map_t     *stack_map;
407         s4               i;
408         u1               frame_type;
409
410         /* get classinfo */
411
412         c = cb->clazz;
413
414         /* allocate stack map structure */
415
416         stack_map = DNEW(stack_map_t);
417
418         STATISTICS(size_stack_map += sizeof(stack_map_t));
419
420         /* check buffer size */
421
422         if (!suck_check_classbuffer_size(cb, 4 + 2))
423                 return false;
424
425         /* attribute_length */
426
427         stack_map->attribute_length = suck_u4(cb);
428
429         if (!suck_check_classbuffer_size(cb, stack_map->attribute_length))
430                 return false;
431
432         /* get number of entries */
433
434         stack_map->number_of_entries = suck_u2(cb);
435
436         /* process all entries */
437
438         stack_map->entries = DMNEW(stack_map_frame_t, stack_map->number_of_entries);
439
440         for (i = 0; i < stack_map->number_of_entries; i++) {
441                 /* get the frame type */
442
443                 frame_type = suck_u1(cb);
444
445                 stack_map->entries[i].frame_type = frame_type;
446
447                 /* process frame */
448
449                 if (frame_type <= FRAME_TYPE_SAME) {
450                         /* same_frame */
451                 }
452                 else if (frame_type <= FRAME_TYPE_SAME_LOCALS_1_STACK_ITEM) {
453                         /* same_locals_1_stack_item_frame */
454
455                         if (!stackmap_get_same_locals_1_stack_item_frame(cb, &(stack_map->entries[i])))
456                                 return false;
457                 }
458                 else if (frame_type <= FRAME_TYPE_RESERVED) {
459                         /* reserved */
460
461                         exceptions_throw_classformaterror(c, "reserved frame type");
462                         return false;
463                 }
464                 else if (frame_type == FRAME_TYPE_SAME_LOCALS_1_STACK_ITEM_EXTENDED) {
465                         /* same_locals_1_stack_item_frame_extended */
466
467                         if (!stackmap_get_same_locals_1_stack_item_frame_extended(cb, &(stack_map->entries[i])))
468                                 return false;
469                 }
470                 else if (frame_type <= FRAME_TYPE_CHOP) {
471                         /* chop_frame */
472
473                         if (!stackmap_get_chop_frame(cb, &(stack_map->entries[i])))
474                                 return false;
475                 }
476                 else if (frame_type == FRAME_TYPE_SAME_FRAME_EXTENDED) {
477                         /* same_frame_extended */
478
479                         if (!stackmap_get_same_frame_extended(cb, &(stack_map->entries[i])))
480                                 return false;
481                 }
482                 else if (frame_type <= FRAME_TYPE_APPEND) {
483                         /* append_frame */
484
485                         if (!stackmap_get_append_frame(cb, &(stack_map->entries[i])))
486                                 return false;
487                 }
488                 else if (frame_type == FRAME_TYPE_FULL_FRAME) {
489                         /* full_frame */
490
491                         if (!stackmap_get_full_frame(cb, &(stack_map->entries[i])))
492                                 return false;
493                 }
494         }
495
496         /* store stack map in method structure */
497
498 #if 0
499         /* currently not used */
500
501         m->stack_map = stack_map;
502 #endif
503
504         return true;
505 }
506
507
508 /*
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  * ---------------------------------------------------------------------
513  * Local variables:
514  * mode: c
515  * indent-tabs-mode: t
516  * c-basic-offset: 4
517  * tab-width: 4
518  * End:
519  * vim:noexpandtab:sw=4:ts=4:
520  */