@@ -2104,7 +2104,6 @@ void ClassFileParser::copy_method_annotations(ConstMethod* cm,
2104
2104
}
2105
2105
}
2106
2106
2107
-
2108
2107
// Note: the parse_method below is big and clunky because all parsing of the code and exceptions
2109
2108
// attribute is inlined. This is cumbersome to avoid since we inline most of the parts in the
2110
2109
// Method* to save footprint, so we only know the size of the resulting Method* when the
@@ -3280,70 +3279,94 @@ void ClassFileParser::parse_classfile_bootstrap_methods_attribute(const ClassFil
3280
3279
3281
3280
cfs->guarantee_more (attribute_byte_length, CHECK);
3282
3281
3283
- const int attribute_array_length = cfs->get_u2_fast ();
3282
+ const u2 num_bootstrap_methods = cfs->get_u2_fast ();
3284
3283
3285
- guarantee_property (_max_bootstrap_specifier_index < attribute_array_length ,
3284
+ guarantee_property (_max_bootstrap_specifier_index < num_bootstrap_methods ,
3286
3285
" Short length on BootstrapMethods in class file %s" ,
3287
3286
CHECK);
3288
3287
3289
-
3290
3288
// The attribute contains a counted array of counted tuples of shorts,
3291
- // represending bootstrap specifiers:
3292
- // length*{bootstrap_method_index, argument_count*{argument_index}}
3293
- const unsigned int operand_count = (attribute_byte_length - (unsigned )sizeof (u2)) / (unsigned )sizeof (u2);
3294
- // operand_count = number of shorts in attr, except for leading length
3295
-
3296
- // The attribute is copied into a short[] array.
3297
- // The array begins with a series of short[2] pairs, one for each tuple.
3298
- const int index_size = (attribute_array_length * 2 );
3299
-
3300
- Array<u2>* const operands =
3301
- MetadataFactory::new_array<u2>(_loader_data, index_size + operand_count, CHECK);
3302
-
3303
- // Eagerly assign operands so they will be deallocated with the constant
3304
- // pool if there is an error.
3305
- cp->set_operands (operands);
3306
-
3307
- int operand_fill_index = index_size;
3289
+ // representing bootstrap specifiers:
3290
+ // length*{bootstrap_method_index, argument_count, argument_count*{argument_index}}
3291
+ const u4 attribute_tail_length = attribute_byte_length - static_cast <u4>(sizeof (u2));
3292
+ assert (attribute_tail_length % sizeof (u2) == 0 , " " );
3293
+ Array<u4>* const offsets =
3294
+ MetadataFactory::new_array<u4>(_loader_data, num_bootstrap_methods, CHECK);
3295
+ Array<u2>* const entries = // u2 data holding all the BSM attribute entries
3296
+ MetadataFactory::new_array<u2>(_loader_data, attribute_tail_length / sizeof (u2), CHECK);
3297
+
3298
+ // Eagerly assign arrays so they will be deallocated with
3299
+ // the constant pool if there is an error.
3300
+ cp->set_bsm_attribute_offsets (offsets);
3301
+ cp->set_bsm_attribute_entries (entries);
3302
+
3303
+ int next_entry = 0 ;
3308
3304
const int cp_size = cp->length ();
3309
3305
3310
- for (int n = 0 ; n < attribute_array_length ; n++) {
3311
- // Store a 32-bit offset into the header of the operand array .
3312
- ConstantPool::operand_offset_at_put (operands, n, operand_fill_index );
3306
+ for (int n = 0 ; n < num_bootstrap_methods ; n++) {
3307
+ // Store a 32-bit offset into the array of BSM entry offsets .
3308
+ offsets-> at_put ( n, next_entry );
3313
3309
3314
- // Read a bootstrap specifier .
3310
+ // Read a bootstrap method attribute entry .
3315
3311
cfs->guarantee_more (sizeof (u2) * 2 , CHECK); // bsm, argc
3316
- const u2 bootstrap_method_index = cfs->get_u2_fast ();
3317
- const u2 argument_count = cfs->get_u2_fast ();
3312
+ const u2 bootstrap_method_ref = cfs->get_u2_fast ();
3313
+ const u2 num_bootstrap_arguments = cfs->get_u2_fast ();
3318
3314
guarantee_property (
3319
- valid_cp_range (bootstrap_method_index , cp_size) &&
3320
- cp->tag_at (bootstrap_method_index ).is_method_handle (),
3315
+ valid_cp_range (bootstrap_method_ref , cp_size) &&
3316
+ cp->tag_at (bootstrap_method_ref ).is_method_handle (),
3321
3317
" bootstrap_method_index %u has bad constant type in class file %s" ,
3322
- bootstrap_method_index ,
3318
+ bootstrap_method_ref ,
3323
3319
CHECK);
3324
3320
3325
- guarantee_property ((operand_fill_index + 1 + argument_count ) < operands ->length (),
3321
+ guarantee_property ((next_entry + 2 + num_bootstrap_arguments ) <= entries ->length (),
3326
3322
" Invalid BootstrapMethods num_bootstrap_methods or num_bootstrap_arguments value in class file %s" ,
3327
3323
CHECK);
3328
3324
3329
- operands->at_put (operand_fill_index++, bootstrap_method_index);
3330
- operands->at_put (operand_fill_index++, argument_count);
3325
+ entries->at_put (next_entry, bootstrap_method_ref);
3326
+ next_entry++;
3327
+ entries->at_put (next_entry, num_bootstrap_arguments);
3328
+ next_entry++;
3331
3329
3332
- cfs->guarantee_more (sizeof (u2) * argument_count , CHECK); // argv[argc]
3333
- for (int j = 0 ; j < argument_count ; j++) {
3330
+ cfs->guarantee_more (sizeof (u2) * num_bootstrap_arguments , CHECK); // argv[argc]
3331
+ for (u2 j = 0 ; j < num_bootstrap_arguments ; j++) {
3334
3332
const u2 argument_index = cfs->get_u2_fast ();
3335
3333
guarantee_property (
3336
3334
valid_cp_range (argument_index, cp_size) &&
3337
3335
cp->tag_at (argument_index).is_loadable_constant (),
3338
3336
" argument_index %u has bad constant type in class file %s" ,
3339
3337
argument_index,
3340
3338
CHECK);
3341
- operands->at_put (operand_fill_index++, argument_index);
3339
+ entries->at_put (next_entry, argument_index);
3340
+ next_entry++;
3342
3341
}
3343
3342
}
3344
3343
guarantee_property (current_start + attribute_byte_length == cfs->current (),
3345
3344
" Bad length on BootstrapMethods in class file %s" ,
3346
3345
CHECK);
3346
+ assert (next_entry == entries->length (), " " );
3347
+
3348
+ #ifdef ASSERT
3349
+ if (num_bootstrap_methods > 0 ) {
3350
+ BSMAttributeEntry* bsme = cp->bsm_attribute_entry (0 );
3351
+ assert (bsme->bootstrap_method_index () == entries->at (0 ), " " );
3352
+ assert (bsme->argument_count () == entries->at (1 ), " " );
3353
+ int nexti = (num_bootstrap_methods == 1 ) ? entries->length () : offsets->at (1 );
3354
+ assert (nexti == 2 + bsme->argument_count (), " " );
3355
+ if (num_bootstrap_methods > 1 ) {
3356
+ bsme = cp->bsm_attribute_entry (1 );
3357
+ assert (bsme->bootstrap_method_index () == entries->at (nexti+0 ), " " );
3358
+ assert (bsme->argument_count () == entries->at (nexti+1 ), " " );
3359
+ }
3360
+ int lasti = offsets->at (offsets->length () - 1 );
3361
+ bsme = cp->bsm_attribute_entry (num_bootstrap_methods - 1 );
3362
+ assert (bsme->bootstrap_method_index () == entries->at (lasti+0 ), " " );
3363
+ assert (bsme->argument_count () == entries->at (lasti+1 ), " " );
3364
+ int lastu2 = entries->at (entries->length () - 1 );
3365
+ int lastac = bsme->argument_count ();
3366
+ int expect_lastu2 = (lastac == 0 ) ? 0 : bsme->argument_index (lastac-1 );
3367
+ assert (lastu2 == expect_lastu2, " " );
3368
+ }
3369
+ #endif
3347
3370
}
3348
3371
3349
3372
void ClassFileParser::parse_classfile_attributes (const ClassFileStream* const cfs,
0 commit comments