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