CACAO
stackmap.cpp
Go to the documentation of this file.
1 /* src/vm/stackmap.c - class attribute StackMapTable
2 
3  Copyright (C) 1996-2013
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.hpp"
28 
29 #include "mm/dumpmemory.hpp"
30 
31 #include "vm/exceptions.hpp"
32 #include "vm/stackmap.hpp"
33 #include "vm/statistics.hpp"
34 #include "vm/options.hpp"
35 #include "vm/suck.hpp"
36 
37 STAT_DECLARE_VAR(int,size_stack_map,0)
38 
39 struct classinfo;
40 
41 using namespace cacao;
42 
43 
44 /* stackmap_get_verification_type_info *****************************************
45 
46  union verification_type_info {
47  Top_variable_info;
48  Integer_variable_info;
49  Float_variable_info;
50  Long_variable_info;
51  Double_variable_info;
52  Null_variable_info;
53  UninitializedThis_variable_info;
54  Object_variable_info;
55  Uninitialized_variable_info;
56  }
57 
58  Top_variable_info {
59  u1 tag = ITEM_Top; // 0
60  }
61 
62  Integer_variable_info {
63  u1 tag = ITEM_Integer; // 1
64  }
65 
66  Float_variable_info {
67  u1 tag = ITEM_Float; // 2
68  }
69 
70  Long_variable_info {
71  u1 tag = ITEM_Long; // 4
72  }
73 
74  Double_variable_info {
75  u1 tag = ITEM_Double; // 3
76  }
77 
78  Null_variable_info {
79  u1 tag = ITEM_Null; // 5
80  }
81 
82  UninitializedThis_variable_info {
83  u1 tag = ITEM_UninitializedThis; // 6
84  }
85 
86  Object_variable_info {
87  u1 tag = ITEM_Object; // 7
88  u2 cpool_index;
89  }
90 
91  Uninitialized_variable_info {
92  u1 tag = ITEM_Uninitialized; // 8
93  u2 offset;
94  }
95 
96 *******************************************************************************/
97 
99 {
100  /* get verification type */
101 
102  if (!cb.check_size(1))
103  return false;
104 
105  verification_type_info->tag = cb.read_u1();
106 
107  /* process the tag */
108 
109  switch (verification_type_info->tag) {
110  case ITEM_Top:
111  case ITEM_Integer:
112  case ITEM_Float:
113  case ITEM_Long:
114  case ITEM_Double:
115  case ITEM_Null:
117  break;
118 
119  case ITEM_Object:
120  /* get constant pool index */
121 
122  if (!cb.check_size(2))
123  return false;
124 
125  verification_type_info->Object_variable_info.cpool_index = cb.read_u2();
126  break;
127 
128  case ITEM_Uninitialized:
129  /* get offset */
130 
131  if (!cb.check_size(2))
132  return false;
133 
134  verification_type_info->Uninitialized_variable_info.offset = cb.read_u2();
135  break;
136  }
137 
138  return true;
139 }
140 
141 
142 /* stackmap_get_same_locals_1_stack_item_frame *********************************
143 
144  same_locals_1_stack_item_frame {
145  u1 frame_type = SAME_LOCALS_1_STACK_ITEM; // 64-127
146  verification_type_info stack[1];
147  }
148 
149 *******************************************************************************/
150 
152 {
153  same_locals_1_stack_item_frame_t *same_locals_1_stack_item_frame;
154 
155  /* for convenience */
156 
157  same_locals_1_stack_item_frame =
158  &(stack_map_frame->same_locals_1_stack_item_frame);
159 
160  if (!stackmap_get_verification_type_info(cb, &(same_locals_1_stack_item_frame->stack[0])))
161  return false;
162 
163  return true;
164 }
165 
166 
167 /* stackmap_get_same_locals_1_stack_item_frame_extended ************************
168 
169  same_locals_1_stack_item_frame_extended {
170  u1 frame_type = SAME_LOCALS_1_STACK_ITEM_EXTENDED; // 247
171  u2 offset_delta;
172  verification_type_info stack[1];
173  }
174 
175 *******************************************************************************/
176 
178 {
179  same_locals_1_stack_item_frame_extended_t *same_locals_1_stack_item_frame_extended;
180 
181  /* for convenience */
182 
183  same_locals_1_stack_item_frame_extended =
184  &(stack_map_frame->same_locals_1_stack_item_frame_extended);
185 
186  /* check buffer size */
187 
188  if (!cb.check_size(2))
189  return false;
190 
191  /* get offset delta */
192 
193  same_locals_1_stack_item_frame_extended->offset_delta = cb.read_u2();
194 
195  /* process stack */
196 
197  if (!stackmap_get_verification_type_info(cb, &(same_locals_1_stack_item_frame_extended->stack[0])))
198  return false;
199 
200  return true;
201 }
202 
203 
204 /* stackmap_get_chop_frame *****************************************************
205 
206  chop_frame {
207  u1 frame_type = CHOP_FRAME; // 248-250
208  u2 offset_delta;
209  }
210 
211 *******************************************************************************/
212 
213 static bool stackmap_get_chop_frame(ClassBuffer& cb, 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 (!cb.check_size(2))
224  return false;
225 
226  /* get offset delta */
227 
228  chop_frame->offset_delta = cb.read_u2();
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 
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 (!cb.check_size(2))
255  return false;
256 
257  /* get offset delta */
258 
259  same_frame_extended->offset_delta = cb.read_u2();
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 
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 (!cb.check_size(2))
289  return false;
290 
291  /* get offset delta */
292 
293  append_frame->offset_delta = cb.read_u2();
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 
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 (!cb.check_size(2 + 2))
337  return false;
338 
339  /* get offset delta */
340 
341  stack_map_frame->full_frame.offset_delta = cb.read_u2();
342 
343  /* get number of locals */
344 
345  full_frame->number_of_locals = cb.read_u2();
346 
347  /* allocate locals array */
348 
349  full_frame->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 (!cb.check_size(2))
361  return false;
362 
363  full_frame->number_of_stack_items = cb.read_u2();
364 
365  /* allocate stack array */
366 
367  full_frame->stack =
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 
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.get_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 (!cb.check_size(4 + 2))
425  return false;
426 
427  /* attribute_length */
428 
429  stack_map->attribute_length = cb.read_u4();
430 
431  if (!cb.check_size(stack_map->attribute_length))
432  return false;
433 
434  /* get number of entries */
435 
436  stack_map->number_of_entries = cb.read_u2();
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 = cb.read_u1();
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 
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  */
verification_type_info_t stack[1]
Definition: stackmap.hpp:146
same_locals_1_stack_item_frame_extended_t same_locals_1_stack_item_frame_extended
Definition: stackmap.hpp:201
stack_map_frame_t * entries
Definition: stackmap.hpp:129
#define STATISTICS(x)
Wrapper for statistics only code.
Definition: statistics.hpp:975
same_frame_extended_t same_frame_extended
Definition: stackmap.hpp:203
static bool stackmap_get_same_locals_1_stack_item_frame(ClassBuffer &cb, stack_map_frame_t *stack_map_frame)
Definition: stackmap.cpp:151
static bool stackmap_get_chop_frame(ClassBuffer &cb, stack_map_frame_t *stack_map_frame)
Definition: stackmap.cpp:213
#define FRAME_TYPE_RESERVED
Definition: stackmap.hpp:191
verification_type_info_t * stack
Definition: stackmap.hpp:183
#define ITEM_Double
Definition: stackmap.hpp:64
void exceptions_throw_classformaterror(classinfo *c, const char *message,...)
Definition: exceptions.cpp:634
uint8_t u1
Definition: types.hpp:40
static bool stackmap_get_verification_type_info(ClassBuffer &cb, verification_type_info_t *verification_type_info)
Definition: stackmap.cpp:98
append_frame_t append_frame
Definition: stackmap.hpp:204
same_locals_1_stack_item_frame_t same_locals_1_stack_item_frame
Definition: stackmap.hpp:200
#define FRAME_TYPE_SAME_LOCALS_1_STACK_ITEM
Definition: stackmap.hpp:190
#define DNEW(type)
Definition: dumpmemory.hpp:370
#define ITEM_Float
Definition: stackmap.hpp:63
verification_type_info_t stack[1]
Definition: stackmap.hpp:137
bool stackmap_load_attribute_stackmaptable(ClassBuffer &cb, methodinfo *m)
Definition: stackmap.cpp:405
uint16_t read_u2()
Definition: suck.hpp:150
#define FRAME_TYPE_FULL_FRAME
Definition: stackmap.hpp:196
This file contains the statistics framework.
full_frame_t full_frame
Definition: stackmap.hpp:205
#define ITEM_Integer
Definition: stackmap.hpp:62
#define ITEM_UninitializedThis
Definition: stackmap.hpp:67
#define FRAME_TYPE_APPEND
Definition: stackmap.hpp:195
#define ITEM_Top
Definition: stackmap.hpp:61
#define FRAME_TYPE_CHOP
Definition: stackmap.hpp:193
#define ITEM_Null
Definition: stackmap.hpp:66
verification_type_info_t * locals
Definition: stackmap.hpp:171
u4 attribute_length
Definition: stackmap.hpp:127
MIIterator i
uint8_t read_u1()
Definition: suck.hpp:145
static bool stackmap_get_full_frame(ClassBuffer &cb, stack_map_frame_t *stack_map_frame)
Definition: stackmap.cpp:324
int32_t s4
Definition: types.hpp:45
#define FRAME_TYPE_SAME_LOCALS_1_STACK_ITEM_EXTENDED
Definition: stackmap.hpp:192
u2 number_of_stack_items
Definition: stackmap.hpp:182
#define ITEM_Uninitialized
Definition: stackmap.hpp:69
static bool stackmap_get_append_frame(ClassBuffer &cb, stack_map_frame_t *stack_map_frame)
Definition: stackmap.cpp:275
uint32_t read_u4()
Definition: suck.hpp:155
#define FRAME_TYPE_SAME
Definition: stackmap.hpp:189
stack_map_t * stack_map
Definition: method.hpp:75
chop_frame_t chop_frame
Definition: stackmap.hpp:202
classinfo * get_class() const
Definition: suck.hpp:117
static bool stackmap_get_same_frame_extended(ClassBuffer &cb, stack_map_frame_t *stack_map_frame)
Definition: stackmap.cpp:243
#define DMNEW(type, num)
Definition: dumpmemory.hpp:371
#define ITEM_Object
Definition: stackmap.hpp:68
bool check_size(size_t sz)
Assert that at least &lt;sz&gt; bytes are left to read.
Definition: suck.hpp:135
u2 number_of_entries
Definition: stackmap.hpp:128
u2 number_of_locals
Definition: stackmap.hpp:180
#define ITEM_Long
Definition: stackmap.hpp:65
static bool stackmap_get_same_locals_1_stack_item_frame_extended(ClassBuffer &cb, stack_map_frame_t *stack_map_frame)
Definition: stackmap.cpp:177
verification_type_info_t * locals
Definition: stackmap.hpp:181
#define STAT_DECLARE_VAR(type, var, init)
Declare an external statistics variable.
Definition: statistics.hpp:963
#define FRAME_TYPE_SAME_FRAME_EXTENDED
Definition: stackmap.hpp:194