Mercurial > hg > graal-jvmci-8
comparison src/share/vm/classfile/stackMapTableFormat.hpp @ 1930:2d26b0046e0d
Merge.
author | Thomas Wuerthinger <wuerthinger@ssw.jku.at> |
---|---|
date | Tue, 30 Nov 2010 14:53:30 +0100 |
parents | a4c7fe54bf3f |
children | f95d63e2154a |
comparison
equal
deleted
inserted
replaced
1484:6b7001391c97 | 1930:2d26b0046e0d |
---|---|
1 /* | |
2 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. | |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
20 * or visit www.oracle.com if you need additional information or have any | |
21 * questions. | |
22 * | |
23 */ | |
24 | |
25 // These classes represent the stack-map substructures described in the JVMS | |
26 // (hence the non-conforming naming scheme). | |
27 | |
28 // These classes work with the types in their compressed form in-place (as they | |
29 // would appear in the classfile). No virtual methods or fields allowed. | |
30 | |
31 class verification_type_info { | |
32 private: | |
33 // u1 tag | |
34 // u2 cpool_index || u2 bci (for ITEM_Object & ITEM_Uninitailized only) | |
35 | |
36 address tag_addr() const { return (address)this; } | |
37 address cpool_index_addr() const { return tag_addr() + sizeof(u1); } | |
38 address bci_addr() const { return cpool_index_addr(); } | |
39 | |
40 protected: | |
41 // No constructors - should be 'private', but GCC issues a warning if it is | |
42 verification_type_info() {} | |
43 verification_type_info(const verification_type_info&) {} | |
44 | |
45 public: | |
46 | |
47 static verification_type_info* at(address addr) { | |
48 return (verification_type_info*)addr; | |
49 } | |
50 | |
51 static verification_type_info* create_at(address addr, u1 tag) { | |
52 verification_type_info* vti = (verification_type_info*)addr; | |
53 vti->set_tag(tag); | |
54 return vti; | |
55 } | |
56 | |
57 static verification_type_info* create_object_at(address addr, u2 cp_idx) { | |
58 verification_type_info* vti = (verification_type_info*)addr; | |
59 vti->set_tag(ITEM_Object); | |
60 vti->set_cpool_index(cp_idx); | |
61 return vti; | |
62 } | |
63 | |
64 static verification_type_info* create_uninit_at(address addr, u2 bci) { | |
65 verification_type_info* vti = (verification_type_info*)addr; | |
66 vti->set_tag(ITEM_Uninitialized); | |
67 vti->set_bci(bci); | |
68 return vti; | |
69 } | |
70 | |
71 static size_t calculate_size(u1 tag) { | |
72 if (tag == ITEM_Object || tag == ITEM_Uninitialized) { | |
73 return sizeof(u1) + sizeof(u2); | |
74 } else { | |
75 return sizeof(u1); | |
76 } | |
77 } | |
78 | |
79 static size_t max_size() { return sizeof(u1) + sizeof(u2); } | |
80 | |
81 u1 tag() const { return *(u1*)tag_addr(); } | |
82 void set_tag(u1 tag) { *((u1*)tag_addr()) = tag; } | |
83 | |
84 bool is_object() const { return tag() == ITEM_Object; } | |
85 bool is_uninitialized() const { return tag() == ITEM_Uninitialized; } | |
86 | |
87 u2 cpool_index() const { | |
88 assert(is_object(), "This type has no cp_index"); | |
89 return Bytes::get_Java_u2(cpool_index_addr()); | |
90 } | |
91 void set_cpool_index(u2 idx) { | |
92 assert(is_object(), "This type has no cp_index"); | |
93 Bytes::put_Java_u2(cpool_index_addr(), idx); | |
94 } | |
95 | |
96 u2 bci() const { | |
97 assert(is_uninitialized(), "This type has no bci"); | |
98 return Bytes::get_Java_u2(bci_addr()); | |
99 } | |
100 | |
101 void set_bci(u2 bci) { | |
102 assert(is_uninitialized(), "This type has no bci"); | |
103 Bytes::put_Java_u2(bci_addr(), bci); | |
104 } | |
105 | |
106 void copy_from(verification_type_info* from) { | |
107 set_tag(from->tag()); | |
108 if (from->is_object()) { | |
109 set_cpool_index(from->cpool_index()); | |
110 } else if (from->is_uninitialized()) { | |
111 set_bci(from->bci()); | |
112 } | |
113 } | |
114 | |
115 size_t size() const { | |
116 return calculate_size(tag()); | |
117 } | |
118 | |
119 verification_type_info* next() { | |
120 return (verification_type_info*)((address)this + size()); | |
121 } | |
122 | |
123 // This method is used when reading unverified data in order to ensure | |
124 // that we don't read past a particular memory limit. It returns false | |
125 // if any part of the data structure is outside the specified memory bounds. | |
126 bool verify(address start, address end) { | |
127 return ((address)this >= start && | |
128 (address)this < end && | |
129 (bci_addr() + sizeof(u2) <= end || | |
130 !is_object() && !is_uninitialized())); | |
131 } | |
132 | |
133 #ifdef ASSERT | |
134 void print_on(outputStream* st) { | |
135 switch (tag()) { | |
136 case ITEM_Top: st->print("Top"); break; | |
137 case ITEM_Integer: st->print("Integer"); break; | |
138 case ITEM_Float: st->print("Float"); break; | |
139 case ITEM_Double: st->print("Double"); break; | |
140 case ITEM_Long: st->print("Long"); break; | |
141 case ITEM_Null: st->print("Null"); break; | |
142 case ITEM_UninitializedThis: | |
143 st->print("UninitializedThis"); break; | |
144 case ITEM_Uninitialized: | |
145 st->print("Uninitialized[#%d]", bci()); break; | |
146 case ITEM_Object: | |
147 st->print("Object[#%d]", cpool_index()); break; | |
148 default: | |
149 assert(false, "Bad verification_type_info"); | |
150 } | |
151 } | |
152 #endif | |
153 }; | |
154 | |
155 #define FOR_EACH_STACKMAP_FRAME_TYPE(macro, arg1, arg2) \ | |
156 macro(same_frame, arg1, arg2) \ | |
157 macro(same_frame_extended, arg1, arg2) \ | |
158 macro(same_frame_1_stack_item_frame, arg1, arg2) \ | |
159 macro(same_frame_1_stack_item_extended, arg1, arg2) \ | |
160 macro(chop_frame, arg1, arg2) \ | |
161 macro(append_frame, arg1, arg2) \ | |
162 macro(full_frame, arg1, arg2) | |
163 | |
164 #define SM_FORWARD_DECL(type, arg1, arg2) class type; | |
165 FOR_EACH_STACKMAP_FRAME_TYPE(SM_FORWARD_DECL, x, x) | |
166 #undef SM_FORWARD_DECL | |
167 | |
168 class stack_map_frame { | |
169 protected: | |
170 address frame_type_addr() const { return (address)this; } | |
171 | |
172 // No constructors - should be 'private', but GCC issues a warning if it is | |
173 stack_map_frame() {} | |
174 stack_map_frame(const stack_map_frame&) {} | |
175 | |
176 public: | |
177 | |
178 static stack_map_frame* at(address addr) { | |
179 return (stack_map_frame*)addr; | |
180 } | |
181 | |
182 stack_map_frame* next() const { | |
183 return at((address)this + size()); | |
184 } | |
185 | |
186 u1 frame_type() const { return *(u1*)frame_type_addr(); } | |
187 void set_frame_type(u1 type) { *((u1*)frame_type_addr()) = type; } | |
188 | |
189 // pseudo-virtual methods | |
190 inline size_t size() const; | |
191 inline int offset_delta() const; | |
192 inline void set_offset_delta(int offset_delta); | |
193 inline int number_of_types() const; // number of types contained in the frame | |
194 inline verification_type_info* types() const; // pointer to first type | |
195 inline bool is_valid_offset(int offset_delta) const; | |
196 | |
197 // This method must be used when reading unverified data in order to ensure | |
198 // that we don't read past a particular memory limit. It returns false | |
199 // if any part of the data structure is outside the specified memory bounds. | |
200 inline bool verify(address start, address end) const; | |
201 #ifdef ASSERT | |
202 inline void print_on(outputStream* st) const; | |
203 #endif | |
204 | |
205 // Create as_xxx and is_xxx methods for the subtypes | |
206 #define FRAME_TYPE_DECL(stackmap_frame_type, arg1, arg2) \ | |
207 inline stackmap_frame_type* as_##stackmap_frame_type() const; \ | |
208 bool is_##stackmap_frame_type() { \ | |
209 return as_##stackmap_frame_type() != NULL; \ | |
210 } | |
211 | |
212 FOR_EACH_STACKMAP_FRAME_TYPE(FRAME_TYPE_DECL, x, x) | |
213 #undef FRAME_TYPE_DECL | |
214 }; | |
215 | |
216 class same_frame : public stack_map_frame { | |
217 private: | |
218 static int frame_type_to_offset_delta(u1 frame_type) { | |
219 return frame_type + 1; } | |
220 static u1 offset_delta_to_frame_type(int offset_delta) { | |
221 return (u1)(offset_delta - 1); } | |
222 | |
223 public: | |
224 | |
225 static bool is_frame_type(u1 tag) { | |
226 return tag < 64; | |
227 } | |
228 | |
229 static same_frame* at(address addr) { | |
230 assert(is_frame_type(*addr), "Wrong frame id"); | |
231 return (same_frame*)addr; | |
232 } | |
233 | |
234 static same_frame* create_at(address addr, int offset_delta) { | |
235 same_frame* sm = (same_frame*)addr; | |
236 sm->set_offset_delta(offset_delta); | |
237 return sm; | |
238 } | |
239 | |
240 static size_t calculate_size() { return sizeof(u1); } | |
241 | |
242 size_t size() const { return calculate_size(); } | |
243 int offset_delta() const { return frame_type_to_offset_delta(frame_type()); } | |
244 | |
245 void set_offset_delta(int offset_delta) { | |
246 assert(offset_delta <= 64, "Offset too large for same_frame"); | |
247 set_frame_type(offset_delta_to_frame_type(offset_delta)); | |
248 } | |
249 | |
250 int number_of_types() const { return 0; } | |
251 verification_type_info* types() const { return NULL; } | |
252 | |
253 bool is_valid_offset(int offset_delta) const { | |
254 return is_frame_type(offset_delta_to_frame_type(offset_delta)); | |
255 } | |
256 | |
257 bool verify_subtype(address start, address end) const { | |
258 return true; | |
259 } | |
260 | |
261 #ifdef ASSERT | |
262 void print_on(outputStream* st) const { | |
263 st->print("same_frame(%d)", offset_delta()); | |
264 } | |
265 #endif | |
266 }; | |
267 | |
268 class same_frame_extended : public stack_map_frame { | |
269 private: | |
270 enum { _frame_id = 251 }; | |
271 address offset_delta_addr() const { return frame_type_addr() + sizeof(u1); } | |
272 | |
273 public: | |
274 static bool is_frame_type(u1 tag) { | |
275 return tag == _frame_id; | |
276 } | |
277 | |
278 static same_frame_extended* at(address addr) { | |
279 assert(is_frame_type(*addr), "Wrong frame type"); | |
280 return (same_frame_extended*)addr; | |
281 } | |
282 | |
283 static same_frame_extended* create_at(address addr, u2 offset_delta) { | |
284 same_frame_extended* sm = (same_frame_extended*)addr; | |
285 sm->set_frame_type(_frame_id); | |
286 sm->set_offset_delta(offset_delta); | |
287 return sm; | |
288 } | |
289 | |
290 static size_t calculate_size() { return sizeof(u1) + sizeof(u2); } | |
291 | |
292 size_t size() const { return calculate_size(); } | |
293 int offset_delta() const { | |
294 return Bytes::get_Java_u2(offset_delta_addr()) + 1; | |
295 } | |
296 | |
297 void set_offset_delta(int offset_delta) { | |
298 Bytes::put_Java_u2(offset_delta_addr(), offset_delta - 1); | |
299 } | |
300 | |
301 int number_of_types() const { return 0; } | |
302 verification_type_info* types() const { return NULL; } | |
303 bool is_valid_offset(int offset) const { return true; } | |
304 | |
305 bool verify_subtype(address start, address end) const { | |
306 return frame_type_addr() + size() <= end; | |
307 } | |
308 | |
309 #ifdef ASSERT | |
310 void print_on(outputStream* st) const { | |
311 st->print("same_frame_extended(%d)", offset_delta()); | |
312 } | |
313 #endif | |
314 }; | |
315 | |
316 class same_frame_1_stack_item_frame : public stack_map_frame { | |
317 private: | |
318 address type_addr() const { return frame_type_addr() + sizeof(u1); } | |
319 | |
320 static int frame_type_to_offset_delta(u1 frame_type) { | |
321 return frame_type - 63; } | |
322 static u1 offset_delta_to_frame_type(int offset_delta) { | |
323 return (u1)(offset_delta + 63); } | |
324 | |
325 public: | |
326 static bool is_frame_type(u1 tag) { | |
327 return tag >= 64 && tag < 128; | |
328 } | |
329 | |
330 static same_frame_1_stack_item_frame* at(address addr) { | |
331 assert(is_frame_type(*addr), "Wrong frame id"); | |
332 return (same_frame_1_stack_item_frame*)addr; | |
333 } | |
334 | |
335 static same_frame_1_stack_item_frame* create_at( | |
336 address addr, int offset_delta, verification_type_info* vti) { | |
337 same_frame_1_stack_item_frame* sm = (same_frame_1_stack_item_frame*)addr; | |
338 sm->set_offset_delta(offset_delta); | |
339 if (vti != NULL) { | |
340 sm->set_type(vti); | |
341 } | |
342 return sm; | |
343 } | |
344 | |
345 static size_t calculate_size(verification_type_info* vti) { | |
346 return sizeof(u1) + vti->size(); | |
347 } | |
348 | |
349 static size_t max_size() { | |
350 return sizeof(u1) + verification_type_info::max_size(); | |
351 } | |
352 | |
353 size_t size() const { return calculate_size(types()); } | |
354 int offset_delta() const { return frame_type_to_offset_delta(frame_type()); } | |
355 | |
356 void set_offset_delta(int offset_delta) { | |
357 assert(offset_delta > 0 && offset_delta <= 64, | |
358 "Offset too large for this frame type"); | |
359 set_frame_type(offset_delta_to_frame_type(offset_delta)); | |
360 } | |
361 | |
362 void set_type(verification_type_info* vti) { | |
363 verification_type_info* cur = types(); | |
364 cur->copy_from(vti); | |
365 } | |
366 | |
367 int number_of_types() const { return 1; } | |
368 verification_type_info* types() const { | |
369 return verification_type_info::at(type_addr()); | |
370 } | |
371 | |
372 bool is_valid_offset(int offset_delta) const { | |
373 return is_frame_type(offset_delta_to_frame_type(offset_delta)); | |
374 } | |
375 | |
376 bool verify_subtype(address start, address end) const { | |
377 return types()->verify(start, end); | |
378 } | |
379 | |
380 #ifdef ASSERT | |
381 void print_on(outputStream* st) const { | |
382 st->print("same_frame_1_stack_item_frame(%d,", offset_delta()); | |
383 types()->print_on(st); | |
384 st->print(")"); | |
385 } | |
386 #endif | |
387 }; | |
388 | |
389 class same_frame_1_stack_item_extended : public stack_map_frame { | |
390 private: | |
391 address offset_delta_addr() const { return frame_type_addr() + sizeof(u1); } | |
392 address type_addr() const { return offset_delta_addr() + sizeof(u2); } | |
393 | |
394 enum { _frame_id = 247 }; | |
395 | |
396 public: | |
397 static bool is_frame_type(u1 tag) { | |
398 return tag == _frame_id; | |
399 } | |
400 | |
401 static same_frame_1_stack_item_extended* at(address addr) { | |
402 assert(is_frame_type(*addr), "Wrong frame id"); | |
403 return (same_frame_1_stack_item_extended*)addr; | |
404 } | |
405 | |
406 static same_frame_1_stack_item_extended* create_at( | |
407 address addr, int offset_delta, verification_type_info* vti) { | |
408 same_frame_1_stack_item_extended* sm = | |
409 (same_frame_1_stack_item_extended*)addr; | |
410 sm->set_frame_type(_frame_id); | |
411 sm->set_offset_delta(offset_delta); | |
412 if (vti != NULL) { | |
413 sm->set_type(vti); | |
414 } | |
415 return sm; | |
416 } | |
417 | |
418 static size_t calculate_size(verification_type_info* vti) { | |
419 return sizeof(u1) + sizeof(u2) + vti->size(); | |
420 } | |
421 | |
422 size_t size() const { return calculate_size(types()); } | |
423 int offset_delta() const { | |
424 return Bytes::get_Java_u2(offset_delta_addr()) + 1; | |
425 } | |
426 | |
427 void set_offset_delta(int offset_delta) { | |
428 Bytes::put_Java_u2(offset_delta_addr(), offset_delta - 1); | |
429 } | |
430 | |
431 void set_type(verification_type_info* vti) { | |
432 verification_type_info* cur = types(); | |
433 cur->copy_from(vti); | |
434 } | |
435 | |
436 int number_of_types() const { return 1; } | |
437 verification_type_info* types() const { | |
438 return verification_type_info::at(type_addr()); | |
439 } | |
440 bool is_valid_offset(int offset) { return true; } | |
441 | |
442 bool verify_subtype(address start, address end) const { | |
443 return type_addr() < end && types()->verify(start, end); | |
444 } | |
445 | |
446 #ifdef ASSERT | |
447 void print_on(outputStream* st) const { | |
448 st->print("same_frame_1_stack_item_extended(%d,", offset_delta()); | |
449 types()->print_on(st); | |
450 st->print(")"); | |
451 } | |
452 #endif | |
453 }; | |
454 | |
455 class chop_frame : public stack_map_frame { | |
456 private: | |
457 address offset_delta_addr() const { return frame_type_addr() + sizeof(u1); } | |
458 | |
459 static int frame_type_to_chops(u1 frame_type) { | |
460 int chop = 251 - frame_type; | |
461 return chop; | |
462 } | |
463 | |
464 static u1 chops_to_frame_type(int chop) { | |
465 return 251 - chop; | |
466 } | |
467 | |
468 public: | |
469 static bool is_frame_type(u1 tag) { | |
470 return frame_type_to_chops(tag) > 0 && frame_type_to_chops(tag) < 4; | |
471 } | |
472 | |
473 static chop_frame* at(address addr) { | |
474 assert(is_frame_type(*addr), "Wrong frame id"); | |
475 return (chop_frame*)addr; | |
476 } | |
477 | |
478 static chop_frame* create_at(address addr, int offset_delta, int chops) { | |
479 chop_frame* sm = (chop_frame*)addr; | |
480 sm->set_chops(chops); | |
481 sm->set_offset_delta(offset_delta); | |
482 return sm; | |
483 } | |
484 | |
485 static size_t calculate_size() { | |
486 return sizeof(u1) + sizeof(u2); | |
487 } | |
488 | |
489 size_t size() const { return calculate_size(); } | |
490 int offset_delta() const { | |
491 return Bytes::get_Java_u2(offset_delta_addr()) + 1; | |
492 } | |
493 void set_offset_delta(int offset_delta) { | |
494 Bytes::put_Java_u2(offset_delta_addr(), offset_delta - 1); | |
495 } | |
496 | |
497 int chops() const { | |
498 int chops = frame_type_to_chops(frame_type()); | |
499 assert(chops > 0 && chops < 4, "Invalid number of chops in frame"); | |
500 return chops; | |
501 } | |
502 void set_chops(int chops) { | |
503 assert(chops > 0 && chops <= 3, "Bad number of chops"); | |
504 set_frame_type(chops_to_frame_type(chops)); | |
505 } | |
506 | |
507 int number_of_types() const { return 0; } | |
508 verification_type_info* types() const { return NULL; } | |
509 bool is_valid_offset(int offset) { return true; } | |
510 | |
511 bool verify_subtype(address start, address end) const { | |
512 return frame_type_addr() + size() <= end; | |
513 } | |
514 | |
515 #ifdef ASSERT | |
516 void print_on(outputStream* st) const { | |
517 st->print("chop_frame(%d,%d)", offset_delta(), chops()); | |
518 } | |
519 #endif | |
520 }; | |
521 | |
522 class append_frame : public stack_map_frame { | |
523 private: | |
524 address offset_delta_addr() const { return frame_type_addr() + sizeof(u1); } | |
525 address types_addr() const { return offset_delta_addr() + sizeof(u2); } | |
526 | |
527 static int frame_type_to_appends(u1 frame_type) { | |
528 int append = frame_type - 251; | |
529 return append; | |
530 } | |
531 | |
532 static u1 appends_to_frame_type(int appends) { | |
533 assert(appends > 0 && appends < 4, "Invalid append amount"); | |
534 return 251 + appends; | |
535 } | |
536 | |
537 public: | |
538 static bool is_frame_type(u1 tag) { | |
539 return frame_type_to_appends(tag) > 0 && frame_type_to_appends(tag) < 4; | |
540 } | |
541 | |
542 static append_frame* at(address addr) { | |
543 assert(is_frame_type(*addr), "Wrong frame id"); | |
544 return (append_frame*)addr; | |
545 } | |
546 | |
547 static append_frame* create_at( | |
548 address addr, int offset_delta, int appends, | |
549 verification_type_info* types) { | |
550 append_frame* sm = (append_frame*)addr; | |
551 sm->set_appends(appends); | |
552 sm->set_offset_delta(offset_delta); | |
553 if (types != NULL) { | |
554 verification_type_info* cur = sm->types(); | |
555 for (int i = 0; i < appends; ++i) { | |
556 cur->copy_from(types); | |
557 cur = cur->next(); | |
558 types = types->next(); | |
559 } | |
560 } | |
561 return sm; | |
562 } | |
563 | |
564 static size_t calculate_size(int appends, verification_type_info* types) { | |
565 size_t sz = sizeof(u1) + sizeof(u2); | |
566 for (int i = 0; i < appends; ++i) { | |
567 sz += types->size(); | |
568 types = types->next(); | |
569 } | |
570 return sz; | |
571 } | |
572 | |
573 static size_t max_size() { | |
574 return sizeof(u1) + sizeof(u2) + 3 * verification_type_info::max_size(); | |
575 } | |
576 | |
577 size_t size() const { return calculate_size(number_of_types(), types()); } | |
578 int offset_delta() const { | |
579 return Bytes::get_Java_u2(offset_delta_addr()) + 1; | |
580 } | |
581 | |
582 void set_offset_delta(int offset_delta) { | |
583 Bytes::put_Java_u2(offset_delta_addr(), offset_delta - 1); | |
584 } | |
585 | |
586 void set_appends(int appends) { | |
587 assert(appends > 0 && appends < 4, "Bad number of appends"); | |
588 set_frame_type(appends_to_frame_type(appends)); | |
589 } | |
590 | |
591 int number_of_types() const { | |
592 int appends = frame_type_to_appends(frame_type()); | |
593 assert(appends > 0 && appends < 4, "Invalid number of appends in frame"); | |
594 return appends; | |
595 } | |
596 verification_type_info* types() const { | |
597 return verification_type_info::at(types_addr()); | |
598 } | |
599 bool is_valid_offset(int offset) const { return true; } | |
600 | |
601 bool verify_subtype(address start, address end) const { | |
602 verification_type_info* vti = types(); | |
603 if ((address)vti < end && vti->verify(start, end)) { | |
604 int nof = number_of_types(); | |
605 vti = vti->next(); | |
606 if (nof < 2 || vti->verify(start, end)) { | |
607 vti = vti->next(); | |
608 if (nof < 3 || vti->verify(start, end)) { | |
609 return true; | |
610 } | |
611 } | |
612 } | |
613 return false; | |
614 } | |
615 | |
616 #ifdef ASSERT | |
617 void print_on(outputStream* st) const { | |
618 st->print("append_frame(%d,", offset_delta()); | |
619 verification_type_info* vti = types(); | |
620 for (int i = 0; i < number_of_types(); ++i) { | |
621 vti->print_on(st); | |
622 if (i != number_of_types() - 1) { | |
623 st->print(","); | |
624 } | |
625 vti = vti->next(); | |
626 } | |
627 st->print(")"); | |
628 } | |
629 #endif | |
630 }; | |
631 | |
632 class full_frame : public stack_map_frame { | |
633 private: | |
634 address offset_delta_addr() const { return frame_type_addr() + sizeof(u1); } | |
635 address num_locals_addr() const { return offset_delta_addr() + sizeof(u2); } | |
636 address locals_addr() const { return num_locals_addr() + sizeof(u2); } | |
637 address stack_slots_addr(address end_of_locals) const { | |
638 return end_of_locals; } | |
639 address stack_addr(address end_of_locals) const { | |
640 return stack_slots_addr(end_of_locals) + sizeof(u2); } | |
641 | |
642 enum { _frame_id = 255 }; | |
643 | |
644 public: | |
645 static bool is_frame_type(u1 tag) { | |
646 return tag == _frame_id; | |
647 } | |
648 | |
649 static full_frame* at(address addr) { | |
650 assert(is_frame_type(*addr), "Wrong frame id"); | |
651 return (full_frame*)addr; | |
652 } | |
653 | |
654 static full_frame* create_at( | |
655 address addr, int offset_delta, int num_locals, | |
656 verification_type_info* locals, | |
657 int stack_slots, verification_type_info* stack) { | |
658 full_frame* sm = (full_frame*)addr; | |
659 sm->set_frame_type(_frame_id); | |
660 sm->set_offset_delta(offset_delta); | |
661 sm->set_num_locals(num_locals); | |
662 if (locals != NULL) { | |
663 verification_type_info* cur = sm->locals(); | |
664 for (int i = 0; i < num_locals; ++i) { | |
665 cur->copy_from(locals); | |
666 cur = cur->next(); | |
667 locals = locals->next(); | |
668 } | |
669 address end_of_locals = (address)cur; | |
670 sm->set_stack_slots(end_of_locals, stack_slots); | |
671 cur = sm->stack(end_of_locals); | |
672 for (int i = 0; i < stack_slots; ++i) { | |
673 cur->copy_from(stack); | |
674 cur = cur->next(); | |
675 stack = stack->next(); | |
676 } | |
677 } | |
678 return sm; | |
679 } | |
680 | |
681 static size_t calculate_size( | |
682 int num_locals, verification_type_info* locals, | |
683 int stack_slots, verification_type_info* stack) { | |
684 size_t sz = sizeof(u1) + sizeof(u2) + sizeof(u2) + sizeof(u2); | |
685 verification_type_info* vti = locals; | |
686 for (int i = 0; i < num_locals; ++i) { | |
687 sz += vti->size(); | |
688 vti = vti->next(); | |
689 } | |
690 vti = stack; | |
691 for (int i = 0; i < stack_slots; ++i) { | |
692 sz += vti->size(); | |
693 vti = vti->next(); | |
694 } | |
695 return sz; | |
696 } | |
697 | |
698 static size_t max_size(int locals, int stack) { | |
699 return sizeof(u1) + 3 * sizeof(u2) + | |
700 (locals + stack) * verification_type_info::max_size(); | |
701 } | |
702 | |
703 size_t size() const { | |
704 address eol = end_of_locals(); | |
705 return calculate_size(num_locals(), locals(), stack_slots(eol), stack(eol)); | |
706 } | |
707 | |
708 int offset_delta() const { | |
709 return Bytes::get_Java_u2(offset_delta_addr()) + 1; | |
710 } | |
711 int num_locals() const { return Bytes::get_Java_u2(num_locals_addr()); } | |
712 verification_type_info* locals() const { | |
713 return verification_type_info::at(locals_addr()); | |
714 } | |
715 address end_of_locals() const { | |
716 verification_type_info* vti = locals(); | |
717 for (int i = 0; i < num_locals(); ++i) { | |
718 vti = vti->next(); | |
719 } | |
720 return (address)vti; | |
721 } | |
722 int stack_slots(address end_of_locals) const { | |
723 return Bytes::get_Java_u2(stack_slots_addr(end_of_locals)); | |
724 } | |
725 verification_type_info* stack(address end_of_locals) const { | |
726 return verification_type_info::at(stack_addr(end_of_locals)); | |
727 } | |
728 | |
729 void set_offset_delta(int offset_delta) { | |
730 Bytes::put_Java_u2(offset_delta_addr(), offset_delta - 1); | |
731 } | |
732 void set_num_locals(int num_locals) { | |
733 Bytes::put_Java_u2(num_locals_addr(), num_locals); | |
734 } | |
735 void set_stack_slots(address end_of_locals, int stack_slots) { | |
736 Bytes::put_Java_u2(stack_slots_addr(end_of_locals), stack_slots); | |
737 } | |
738 | |
739 // These return only the locals. Extra processing is required for stack | |
740 // types of full frames. | |
741 int number_of_types() const { return num_locals(); } | |
742 verification_type_info* types() const { return locals(); } | |
743 bool is_valid_offset(int offset) { return true; } | |
744 | |
745 bool verify_subtype(address start, address end) const { | |
746 verification_type_info* vti = types(); | |
747 if ((address)vti >= end) { | |
748 return false; | |
749 } | |
750 int count = number_of_types(); | |
751 for (int i = 0; i < count; ++i) { | |
752 if (!vti->verify(start, end)) { | |
753 return false; | |
754 } | |
755 vti = vti->next(); | |
756 } | |
757 address eol = (address)vti; | |
758 if (eol + sizeof(u2) > end) { | |
759 return false; | |
760 } | |
761 count = stack_slots(eol); | |
762 vti = stack(eol); | |
763 for (int i = 0; i < stack_slots(eol); ++i) { | |
764 if (!vti->verify(start, end)) { | |
765 return false; | |
766 } | |
767 vti = vti->next(); | |
768 } | |
769 return true; | |
770 } | |
771 | |
772 #ifdef ASSERT | |
773 void print_on(outputStream* st) const { | |
774 st->print("full_frame(%d,{", offset_delta()); | |
775 verification_type_info* vti = locals(); | |
776 for (int i = 0; i < num_locals(); ++i) { | |
777 vti->print_on(st); | |
778 if (i != num_locals() - 1) { | |
779 st->print(","); | |
780 } | |
781 vti = vti->next(); | |
782 } | |
783 st->print("},{"); | |
784 address end_of_locals = (address)vti; | |
785 vti = stack(end_of_locals); | |
786 int ss = stack_slots(end_of_locals); | |
787 for (int i = 0; i < ss; ++i) { | |
788 vti->print_on(st); | |
789 if (i != ss - 1) { | |
790 st->print(","); | |
791 } | |
792 vti = vti->next(); | |
793 } | |
794 st->print("})"); | |
795 } | |
796 #endif | |
797 }; | |
798 | |
799 #define VIRTUAL_DISPATCH(stack_frame_type, func_name, args) \ | |
800 stack_frame_type* item_##stack_frame_type = as_##stack_frame_type(); \ | |
801 if (item_##stack_frame_type != NULL) { \ | |
802 return item_##stack_frame_type->func_name args; \ | |
803 } | |
804 | |
805 #define VOID_VIRTUAL_DISPATCH(stack_frame_type, func_name, args) \ | |
806 stack_frame_type* item_##stack_frame_type = as_##stack_frame_type(); \ | |
807 if (item_##stack_frame_type != NULL) { \ | |
808 item_##stack_frame_type->func_name args; \ | |
809 return; \ | |
810 } | |
811 | |
812 size_t stack_map_frame::size() const { | |
813 FOR_EACH_STACKMAP_FRAME_TYPE(VIRTUAL_DISPATCH, size, ()); | |
814 return 0; | |
815 } | |
816 | |
817 int stack_map_frame::offset_delta() const { | |
818 FOR_EACH_STACKMAP_FRAME_TYPE(VIRTUAL_DISPATCH, offset_delta, ()); | |
819 return 0; | |
820 } | |
821 | |
822 void stack_map_frame::set_offset_delta(int offset_delta) { | |
823 FOR_EACH_STACKMAP_FRAME_TYPE( | |
824 VOID_VIRTUAL_DISPATCH, set_offset_delta, (offset_delta)); | |
825 } | |
826 | |
827 int stack_map_frame::number_of_types() const { | |
828 FOR_EACH_STACKMAP_FRAME_TYPE(VIRTUAL_DISPATCH, number_of_types, ()); | |
829 return 0; | |
830 } | |
831 | |
832 verification_type_info* stack_map_frame::types() const { | |
833 FOR_EACH_STACKMAP_FRAME_TYPE(VIRTUAL_DISPATCH, types, ()); | |
834 return NULL; | |
835 } | |
836 | |
837 bool stack_map_frame::is_valid_offset(int offset) const { | |
838 FOR_EACH_STACKMAP_FRAME_TYPE(VIRTUAL_DISPATCH, is_valid_offset, (offset)); | |
839 return true; | |
840 } | |
841 | |
842 bool stack_map_frame::verify(address start, address end) const { | |
843 if (frame_type_addr() >= start && frame_type_addr() < end) { | |
844 FOR_EACH_STACKMAP_FRAME_TYPE( | |
845 VIRTUAL_DISPATCH, verify_subtype, (start, end)); | |
846 } | |
847 return false; | |
848 } | |
849 | |
850 #ifdef ASSERT | |
851 void stack_map_frame::print_on(outputStream* st) const { | |
852 FOR_EACH_STACKMAP_FRAME_TYPE(VOID_VIRTUAL_DISPATCH, print_on, (st)); | |
853 } | |
854 #endif | |
855 | |
856 #undef VIRTUAL_DISPATCH | |
857 #undef VOID_VIRTUAL_DISPATCH | |
858 | |
859 #define AS_SUBTYPE_DEF(stack_frame_type, arg1, arg2) \ | |
860 stack_frame_type* stack_map_frame::as_##stack_frame_type() const { \ | |
861 if (stack_frame_type::is_frame_type(frame_type())) { \ | |
862 return (stack_frame_type*)this; \ | |
863 } else { \ | |
864 return NULL; \ | |
865 } \ | |
866 } | |
867 | |
868 FOR_EACH_STACKMAP_FRAME_TYPE(AS_SUBTYPE_DEF, x, x) | |
869 #undef AS_SUBTYPE_DEF | |
870 | |
871 class stack_map_table_attribute { | |
872 private: | |
873 address name_index_addr() const { | |
874 return (address)this; } | |
875 address attribute_length_addr() const { | |
876 return name_index_addr() + sizeof(u2); } | |
877 address number_of_entries_addr() const { | |
878 return attribute_length_addr() + sizeof(u4); } | |
879 address entries_addr() const { | |
880 return number_of_entries_addr() + sizeof(u2); } | |
881 | |
882 protected: | |
883 // No constructors - should be 'private', but GCC issues a warning if it is | |
884 stack_map_table_attribute() {} | |
885 stack_map_table_attribute(const stack_map_table_attribute&) {} | |
886 | |
887 public: | |
888 | |
889 static stack_map_table_attribute* at(address addr) { | |
890 return (stack_map_table_attribute*)addr; | |
891 } | |
892 | |
893 u2 name_index() const { | |
894 return Bytes::get_Java_u2(name_index_addr()); } | |
895 u4 attribute_length() const { | |
896 return Bytes::get_Java_u4(attribute_length_addr()); } | |
897 u2 number_of_entries() const { | |
898 return Bytes::get_Java_u2(number_of_entries_addr()); } | |
899 stack_map_frame* entries() const { | |
900 return stack_map_frame::at(entries_addr()); | |
901 } | |
902 | |
903 static size_t header_size() { | |
904 return sizeof(u2) + sizeof(u4); | |
905 } | |
906 | |
907 void set_name_index(u2 idx) { | |
908 Bytes::put_Java_u2(name_index_addr(), idx); | |
909 } | |
910 void set_attribute_length(u4 len) { | |
911 Bytes::put_Java_u4(attribute_length_addr(), len); | |
912 } | |
913 void set_number_of_entries(u2 num) { | |
914 Bytes::put_Java_u2(number_of_entries_addr(), num); | |
915 } | |
916 }; |