29
29
#include " oops/oop.inline.hpp"
30
30
#include " runtime/handles.inline.hpp"
31
31
32
- StackMapTable::StackMapTable (StackMapReader* reader, StackMapFrame* init_frame,
33
- u2 max_locals, u2 max_stack,
34
- char * code_data, int code_len, TRAPS) {
35
- _code_length = code_len;
32
+ StackMapTable::StackMapTable (StackMapReader* reader, TRAPS) {
33
+ _code_length = reader->code_length ();
36
34
_frame_count = reader->get_frame_count ();
37
35
if (_frame_count > 0 ) {
38
- _frame_array = NEW_RESOURCE_ARRAY_IN_THREAD (THREAD,
39
- StackMapFrame*, _frame_count);
40
- StackMapFrame* pre_frame = init_frame;
41
- for (int32_t i = 0 ; i < _frame_count; i++) {
42
- StackMapFrame* frame = reader->next (
43
- pre_frame, i == 0 , max_locals, max_stack,
44
- CHECK_VERIFY (pre_frame->verifier ()));
45
- _frame_array[i] = frame;
46
- int offset = frame->offset ();
47
- if (offset >= code_len || code_data[offset] == 0 ) {
48
- frame->verifier ()->verify_error (
49
- ErrorContext::bad_stackmap (i, frame),
50
- " StackMapTable error: bad offset" );
51
- return ;
36
+ _frame_array = new GrowableArray<StackMapFrame*>(_frame_count);
37
+ while (!reader->at_end ()) {
38
+ StackMapFrame* frame = reader->next (CHECK_VERIFY (reader->prev_frame ()->verifier ()));
39
+ if (frame != nullptr ) {
40
+ _frame_array->push (frame);
52
41
}
53
- pre_frame = frame;
54
42
}
43
+ reader->check_end (CHECK);
44
+ // Correct frame count based on how many actual frames are generated
45
+ _frame_count = _frame_array->length ();
46
+ }
47
+ }
48
+
49
+ void StackMapReader::check_offset (StackMapFrame* frame) {
50
+ int offset = frame->offset ();
51
+ if (offset >= _code_length || _code_data[offset] == 0 ) {
52
+ _verifier->verify_error (ErrorContext::bad_stackmap (0 , frame),
53
+ " StackMapTable error: bad offset" );
54
+ }
55
+ }
56
+
57
+ void StackMapReader::check_size (TRAPS) {
58
+ if (_frame_count < _parsed_frame_count) {
59
+ StackMapStream::stackmap_format_error (" wrong attribute size" , THREAD);
60
+ }
61
+ }
62
+
63
+ void StackMapReader::check_end (TRAPS) {
64
+ assert (_stream->at_end (), " must be" );
65
+ if (_frame_count != _parsed_frame_count) {
66
+ StackMapStream::stackmap_format_error (" wrong attribute size" , THREAD);
55
67
}
56
- reader->check_end (CHECK);
57
68
}
58
69
59
70
// This method is only called by method in StackMapTable.
60
71
int StackMapTable::get_index_from_offset (int32_t offset) const {
61
72
int i = 0 ;
62
73
for (; i < _frame_count; i++) {
63
- if (_frame_array[i] ->offset () == offset) {
74
+ if (_frame_array-> at (i) ->offset () == offset) {
64
75
return i;
65
76
}
66
77
}
@@ -95,7 +106,7 @@ bool StackMapTable::match_stackmap(
95
106
return false ;
96
107
}
97
108
98
- StackMapFrame * stackmap_frame = _frame_array[ frame_index] ;
109
+ StackMapFrame* stackmap_frame = _frame_array-> at ( frame_index) ;
99
110
bool result = true ;
100
111
if (match) {
101
112
// Has direct control flow from last instruction, need to match the two
@@ -137,16 +148,20 @@ void StackMapTable::print_on(outputStream* str) const {
137
148
{
138
149
streamIndentor si (str);
139
150
for (int32_t i = 0 ; i < _frame_count; ++i) {
140
- _frame_array[i] ->print_on (str);
151
+ _frame_array-> at (i) ->print_on (str);
141
152
}
142
153
}
143
154
str->print_cr (" }" );
144
155
}
145
156
146
- StackMapReader::StackMapReader (ClassVerifier* v, StackMapStream* stream, char * code_data,
147
- int32_t code_len, TRAPS) :
148
- _verifier(v), _stream(stream),
149
- _code_data(code_data), _code_length(code_len) {
157
+ StackMapReader::StackMapReader (ClassVerifier* v, StackMapStream* stream,
158
+ char * code_data, int32_t code_len,
159
+ StackMapFrame* init_frame,
160
+ u2 max_locals, u2 max_stack, TRAPS) :
161
+ _verifier(v), _stream(stream), _code_data(code_data),
162
+ _code_length(code_len), _parsed_frame_count(0 ),
163
+ _prev_frame(init_frame), _max_locals(max_locals),
164
+ _max_stack(max_stack), _first(true ) {
150
165
methodHandle m = v->method ();
151
166
if (m->has_stackmap_table ()) {
152
167
_cp = constantPoolHandle (THREAD, m->constants ());
@@ -210,45 +225,56 @@ VerificationType StackMapReader::parse_verification_type(u1* flags, TRAPS) {
210
225
return VerificationType::bogus_type ();
211
226
}
212
227
213
- StackMapFrame* StackMapReader::next (
214
- StackMapFrame* pre_frame, bool first, u2 max_locals, u2 max_stack, TRAPS) {
228
+ StackMapFrame* StackMapReader::next (TRAPS) {
229
+ _parsed_frame_count++;
230
+ check_size (CHECK_NULL);
231
+ StackMapFrame* frame = next_helper (CHECK_VERIFY_ (_verifier, nullptr ));
232
+ if (frame != nullptr ) {
233
+ check_offset (frame);
234
+ _prev_frame = frame;
235
+ }
236
+ return frame;
237
+ }
238
+
239
+ StackMapFrame* StackMapReader::next_helper (TRAPS) {
215
240
StackMapFrame* frame;
216
241
int offset;
217
242
VerificationType* locals = nullptr ;
218
243
u1 frame_type = _stream->get_u1 (CHECK_NULL);
219
244
if (frame_type < 64 ) {
220
245
// same_frame
221
- if (first ) {
246
+ if (_first ) {
222
247
offset = frame_type;
223
248
// Can't share the locals array since that is updated by the verifier.
224
- if (pre_frame ->locals_size () > 0 ) {
249
+ if (_prev_frame ->locals_size () > 0 ) {
225
250
locals = NEW_RESOURCE_ARRAY_IN_THREAD (
226
- THREAD, VerificationType, pre_frame ->locals_size ());
251
+ THREAD, VerificationType, _prev_frame ->locals_size ());
227
252
}
228
253
} else {
229
- offset = pre_frame ->offset () + frame_type + 1 ;
230
- locals = pre_frame ->locals ();
254
+ offset = _prev_frame ->offset () + frame_type + 1 ;
255
+ locals = _prev_frame ->locals ();
231
256
}
232
257
frame = new StackMapFrame (
233
- offset, pre_frame ->flags (), pre_frame ->locals_size (), 0 ,
234
- max_locals, max_stack , locals, nullptr , _verifier);
235
- if (first && locals != nullptr ) {
236
- frame->copy_locals (pre_frame );
258
+ offset, _prev_frame ->flags (), _prev_frame ->locals_size (), 0 ,
259
+ _max_locals, _max_stack , locals, nullptr , _verifier);
260
+ if (_first && locals != nullptr ) {
261
+ frame->copy_locals (_prev_frame );
237
262
}
263
+ _first = false ;
238
264
return frame;
239
265
}
240
266
if (frame_type < 128 ) {
241
267
// same_locals_1_stack_item_frame
242
- if (first ) {
268
+ if (_first ) {
243
269
offset = frame_type - 64 ;
244
270
// Can't share the locals array since that is updated by the verifier.
245
- if (pre_frame ->locals_size () > 0 ) {
271
+ if (_prev_frame ->locals_size () > 0 ) {
246
272
locals = NEW_RESOURCE_ARRAY_IN_THREAD (
247
- THREAD, VerificationType, pre_frame ->locals_size ());
273
+ THREAD, VerificationType, _prev_frame ->locals_size ());
248
274
}
249
275
} else {
250
- offset = pre_frame ->offset () + frame_type - 63 ;
251
- locals = pre_frame ->locals ();
276
+ offset = _prev_frame ->offset () + frame_type - 63 ;
277
+ locals = _prev_frame ->locals ();
252
278
}
253
279
VerificationType* stack = NEW_RESOURCE_ARRAY_IN_THREAD (
254
280
THREAD, VerificationType, 2 );
@@ -259,13 +285,14 @@ StackMapFrame* StackMapReader::next(
259
285
stack_size = 2 ;
260
286
}
261
287
check_verification_type_array_size (
262
- stack_size, max_stack , CHECK_VERIFY_ (_verifier, nullptr ));
288
+ stack_size, _max_stack , CHECK_VERIFY_ (_verifier, nullptr ));
263
289
frame = new StackMapFrame (
264
- offset, pre_frame ->flags (), pre_frame ->locals_size (), stack_size,
265
- max_locals, max_stack , locals, stack, _verifier);
266
- if (first && locals != nullptr ) {
267
- frame->copy_locals (pre_frame );
290
+ offset, _prev_frame ->flags (), _prev_frame ->locals_size (), stack_size,
291
+ _max_locals, _max_stack , locals, stack, _verifier);
292
+ if (_first && locals != nullptr ) {
293
+ frame->copy_locals (_prev_frame );
268
294
}
295
+ _first = false ;
269
296
return frame;
270
297
}
271
298
@@ -279,16 +306,16 @@ StackMapFrame* StackMapReader::next(
279
306
280
307
if (frame_type == SAME_LOCALS_1_STACK_ITEM_EXTENDED) {
281
308
// same_locals_1_stack_item_frame_extended
282
- if (first ) {
309
+ if (_first ) {
283
310
offset = offset_delta;
284
311
// Can't share the locals array since that is updated by the verifier.
285
- if (pre_frame ->locals_size () > 0 ) {
312
+ if (_prev_frame ->locals_size () > 0 ) {
286
313
locals = NEW_RESOURCE_ARRAY_IN_THREAD (
287
- THREAD, VerificationType, pre_frame ->locals_size ());
314
+ THREAD, VerificationType, _prev_frame ->locals_size ());
288
315
}
289
316
} else {
290
- offset = pre_frame ->offset () + offset_delta + 1 ;
291
- locals = pre_frame ->locals ();
317
+ offset = _prev_frame ->offset () + offset_delta + 1 ;
318
+ locals = _prev_frame ->locals ();
292
319
}
293
320
VerificationType* stack = NEW_RESOURCE_ARRAY_IN_THREAD (
294
321
THREAD, VerificationType, 2 );
@@ -299,27 +326,28 @@ StackMapFrame* StackMapReader::next(
299
326
stack_size = 2 ;
300
327
}
301
328
check_verification_type_array_size (
302
- stack_size, max_stack , CHECK_VERIFY_ (_verifier, nullptr ));
329
+ stack_size, _max_stack , CHECK_VERIFY_ (_verifier, nullptr ));
303
330
frame = new StackMapFrame (
304
- offset, pre_frame ->flags (), pre_frame ->locals_size (), stack_size,
305
- max_locals, max_stack , locals, stack, _verifier);
306
- if (first && locals != nullptr ) {
307
- frame->copy_locals (pre_frame );
331
+ offset, _prev_frame ->flags (), _prev_frame ->locals_size (), stack_size,
332
+ _max_locals, _max_stack , locals, stack, _verifier);
333
+ if (_first && locals != nullptr ) {
334
+ frame->copy_locals (_prev_frame );
308
335
}
336
+ _first = false ;
309
337
return frame;
310
338
}
311
339
312
340
if (frame_type <= SAME_EXTENDED) {
313
341
// chop_frame or same_frame_extended
314
- locals = pre_frame ->locals ();
315
- int length = pre_frame ->locals_size ();
342
+ locals = _prev_frame ->locals ();
343
+ int length = _prev_frame ->locals_size ();
316
344
int chops = SAME_EXTENDED - frame_type;
317
345
int new_length = length;
318
- u1 flags = pre_frame ->flags ();
346
+ u1 flags = _prev_frame ->flags ();
319
347
if (chops != 0 ) {
320
348
new_length = chop (locals, length, chops);
321
349
check_verification_type_array_size (
322
- new_length, max_locals , CHECK_VERIFY_ (_verifier, nullptr ));
350
+ new_length, _max_locals , CHECK_VERIFY_ (_verifier, nullptr ));
323
351
// Recompute flags since uninitializedThis could have been chopped.
324
352
flags = 0 ;
325
353
for (int i=0 ; i<new_length; i++) {
@@ -329,7 +357,7 @@ StackMapFrame* StackMapReader::next(
329
357
}
330
358
}
331
359
}
332
- if (first ) {
360
+ if (_first ) {
333
361
offset = offset_delta;
334
362
// Can't share the locals array since that is updated by the verifier.
335
363
if (new_length > 0 ) {
@@ -339,28 +367,28 @@ StackMapFrame* StackMapReader::next(
339
367
locals = nullptr ;
340
368
}
341
369
} else {
342
- offset = pre_frame ->offset () + offset_delta + 1 ;
370
+ offset = _prev_frame ->offset () + offset_delta + 1 ;
343
371
}
344
372
frame = new StackMapFrame (
345
- offset, flags, new_length, 0 , max_locals, max_stack ,
373
+ offset, flags, new_length, 0 , _max_locals, _max_stack ,
346
374
locals, nullptr , _verifier);
347
- if (first && locals != nullptr ) {
348
- frame->copy_locals (pre_frame );
375
+ if (_first && locals != nullptr ) {
376
+ frame->copy_locals (_prev_frame );
349
377
}
378
+ _first = false ;
350
379
return frame;
351
380
} else if (frame_type < SAME_EXTENDED + 4 ) {
352
381
// append_frame
353
382
int appends = frame_type - SAME_EXTENDED;
354
- int real_length = pre_frame ->locals_size ();
383
+ int real_length = _prev_frame ->locals_size ();
355
384
int new_length = real_length + appends*2 ;
356
385
locals = NEW_RESOURCE_ARRAY_IN_THREAD (THREAD, VerificationType, new_length);
357
- VerificationType* pre_locals = pre_frame->locals ();
358
- int i;
359
- for (i=0 ; i<pre_frame->locals_size (); i++) {
386
+ VerificationType* pre_locals = _prev_frame->locals ();
387
+ for (int i = 0 ; i < _prev_frame->locals_size (); i++) {
360
388
locals[i] = pre_locals[i];
361
389
}
362
- u1 flags = pre_frame ->flags ();
363
- for (i= 0 ; i< appends; i++) {
390
+ u1 flags = _prev_frame ->flags ();
391
+ for (int i = 0 ; i < appends; i++) {
364
392
locals[real_length] = parse_verification_type (&flags, CHECK_NULL);
365
393
if (locals[real_length].is_category2 ()) {
366
394
locals[real_length + 1 ] = locals[real_length].to_category2_2nd ();
@@ -369,15 +397,16 @@ StackMapFrame* StackMapReader::next(
369
397
++real_length;
370
398
}
371
399
check_verification_type_array_size (
372
- real_length, max_locals , CHECK_VERIFY_ (_verifier, nullptr ));
373
- if (first ) {
400
+ real_length, _max_locals , CHECK_VERIFY_ (_verifier, nullptr ));
401
+ if (_first ) {
374
402
offset = offset_delta;
375
403
} else {
376
- offset = pre_frame ->offset () + offset_delta + 1 ;
404
+ offset = _prev_frame ->offset () + offset_delta + 1 ;
377
405
}
378
406
frame = new StackMapFrame (
379
- offset, flags, real_length, 0 , max_locals,
380
- max_stack, locals, nullptr , _verifier);
407
+ offset, flags, real_length, 0 , _max_locals,
408
+ _max_stack, locals, nullptr , _verifier);
409
+ _first = false ;
381
410
return frame;
382
411
}
383
412
if (frame_type == FULL) {
@@ -389,8 +418,7 @@ StackMapFrame* StackMapReader::next(
389
418
locals = NEW_RESOURCE_ARRAY_IN_THREAD (
390
419
THREAD, VerificationType, locals_size*2 );
391
420
}
392
- int i;
393
- for (i=0 ; i<locals_size; i++) {
421
+ for (int i = 0 ; i < locals_size; i++) {
394
422
locals[real_locals_size] = parse_verification_type (&flags, CHECK_NULL);
395
423
if (locals[real_locals_size].is_category2 ()) {
396
424
locals[real_locals_size + 1 ] =
@@ -400,15 +428,15 @@ StackMapFrame* StackMapReader::next(
400
428
++real_locals_size;
401
429
}
402
430
check_verification_type_array_size (
403
- real_locals_size, max_locals , CHECK_VERIFY_ (_verifier, nullptr ));
431
+ real_locals_size, _max_locals , CHECK_VERIFY_ (_verifier, nullptr ));
404
432
u2 stack_size = _stream->get_u2 (CHECK_NULL);
405
433
int real_stack_size = 0 ;
406
434
VerificationType* stack = nullptr ;
407
435
if (stack_size > 0 ) {
408
436
stack = NEW_RESOURCE_ARRAY_IN_THREAD (
409
437
THREAD, VerificationType, stack_size*2 );
410
438
}
411
- for (i= 0 ; i< stack_size; i++) {
439
+ for (int i = 0 ; i < stack_size; i++) {
412
440
stack[real_stack_size] = parse_verification_type (nullptr , CHECK_NULL);
413
441
if (stack[real_stack_size].is_category2 ()) {
414
442
stack[real_stack_size + 1 ] = stack[real_stack_size].to_category2_2nd ();
@@ -417,19 +445,20 @@ StackMapFrame* StackMapReader::next(
417
445
++real_stack_size;
418
446
}
419
447
check_verification_type_array_size (
420
- real_stack_size, max_stack , CHECK_VERIFY_ (_verifier, nullptr ));
421
- if (first ) {
448
+ real_stack_size, _max_stack , CHECK_VERIFY_ (_verifier, nullptr ));
449
+ if (_first ) {
422
450
offset = offset_delta;
423
451
} else {
424
- offset = pre_frame ->offset () + offset_delta + 1 ;
452
+ offset = _prev_frame ->offset () + offset_delta + 1 ;
425
453
}
426
454
frame = new StackMapFrame (
427
455
offset, flags, real_locals_size, real_stack_size,
428
- max_locals, max_stack, locals, stack, _verifier);
456
+ _max_locals, _max_stack, locals, stack, _verifier);
457
+ _first = false ;
429
458
return frame;
430
459
}
431
460
432
461
_stream->stackmap_format_error (
433
- " reserved frame type" , CHECK_VERIFY_ (pre_frame ->verifier (), nullptr ));
462
+ " reserved frame type" , CHECK_VERIFY_ (_prev_frame ->verifier (), nullptr ));
434
463
return nullptr ;
435
464
}
0 commit comments