comparison src/share/vm/classfile/classFileParser.cpp @ 938:b37c246bf7ce

6861660: OopMapBlock count/size confusion Reviewed-by: tonyp, iveresov
author jcoomes
date Tue, 11 Aug 2009 15:37:23 -0700
parents 494244ae0171
children 9eebd3ac74cf
comparison
equal deleted inserted replaced
937:ead53f6b615d 938:b37c246bf7ce
2922 nonstatic_oop_count) != 0); 2922 nonstatic_oop_count) != 0);
2923 2923
2924 2924
2925 // Prepare list of oops for oop maps generation. 2925 // Prepare list of oops for oop maps generation.
2926 u2* nonstatic_oop_offsets; 2926 u2* nonstatic_oop_offsets;
2927 u2* nonstatic_oop_length; 2927 u2* nonstatic_oop_counts;
2928 int nonstatic_oop_map_count = 0; 2928 int nonstatic_oop_map_count = 0;
2929 2929
2930 nonstatic_oop_offsets = NEW_RESOURCE_ARRAY_IN_THREAD( 2930 nonstatic_oop_offsets = NEW_RESOURCE_ARRAY_IN_THREAD(
2931 THREAD, u2, nonstatic_oop_count+1); 2931 THREAD, u2, nonstatic_oop_count+1);
2932 nonstatic_oop_length = NEW_RESOURCE_ARRAY_IN_THREAD( 2932 nonstatic_oop_counts = NEW_RESOURCE_ARRAY_IN_THREAD(
2933 THREAD, u2, nonstatic_oop_count+1); 2933 THREAD, u2, nonstatic_oop_count+1);
2934 2934
2935 // Add fake fields for java.lang.Class instances (also see above). 2935 // Add fake fields for java.lang.Class instances (also see above).
2936 // FieldsAllocationStyle and CompactFields values will be reset to default. 2936 // FieldsAllocationStyle and CompactFields values will be reset to default.
2937 if(class_name() == vmSymbols::java_lang_Class() && class_loader.is_null()) { 2937 if(class_name() == vmSymbols::java_lang_Class() && class_loader.is_null()) {
2938 java_lang_Class_fix_post(&next_nonstatic_field_offset); 2938 java_lang_Class_fix_post(&next_nonstatic_field_offset);
2939 nonstatic_oop_offsets[0] = (u2)first_nonstatic_field_offset; 2939 nonstatic_oop_offsets[0] = (u2)first_nonstatic_field_offset;
2940 int fake_oop_count = (( next_nonstatic_field_offset - 2940 int fake_oop_count = (( next_nonstatic_field_offset -
2941 first_nonstatic_field_offset ) / heapOopSize); 2941 first_nonstatic_field_offset ) / heapOopSize);
2942 nonstatic_oop_length [0] = (u2)fake_oop_count; 2942 nonstatic_oop_counts [0] = (u2)fake_oop_count;
2943 nonstatic_oop_map_count = 1; 2943 nonstatic_oop_map_count = 1;
2944 nonstatic_oop_count -= fake_oop_count; 2944 nonstatic_oop_count -= fake_oop_count;
2945 first_nonstatic_oop_offset = first_nonstatic_field_offset; 2945 first_nonstatic_oop_offset = first_nonstatic_field_offset;
2946 } else { 2946 } else {
2947 first_nonstatic_oop_offset = 0; // will be set for first oop field 2947 first_nonstatic_oop_offset = 0; // will be set for first oop field
3117 next_nonstatic_oop_offset += heapOopSize; 3117 next_nonstatic_oop_offset += heapOopSize;
3118 } 3118 }
3119 // Update oop maps 3119 // Update oop maps
3120 if( nonstatic_oop_map_count > 0 && 3120 if( nonstatic_oop_map_count > 0 &&
3121 nonstatic_oop_offsets[nonstatic_oop_map_count - 1] == 3121 nonstatic_oop_offsets[nonstatic_oop_map_count - 1] ==
3122 (u2)(real_offset - nonstatic_oop_length[nonstatic_oop_map_count - 1] * heapOopSize) ) { 3122 (u2)(real_offset - nonstatic_oop_counts[nonstatic_oop_map_count - 1] * heapOopSize) ) {
3123 // Extend current oop map 3123 // Extend current oop map
3124 nonstatic_oop_length[nonstatic_oop_map_count - 1] += 1; 3124 nonstatic_oop_counts[nonstatic_oop_map_count - 1] += 1;
3125 } else { 3125 } else {
3126 // Create new oop map 3126 // Create new oop map
3127 nonstatic_oop_offsets[nonstatic_oop_map_count] = (u2)real_offset; 3127 nonstatic_oop_offsets[nonstatic_oop_map_count] = (u2)real_offset;
3128 nonstatic_oop_length [nonstatic_oop_map_count] = 1; 3128 nonstatic_oop_counts [nonstatic_oop_map_count] = 1;
3129 nonstatic_oop_map_count += 1; 3129 nonstatic_oop_map_count += 1;
3130 if( first_nonstatic_oop_offset == 0 ) { // Undefined 3130 if( first_nonstatic_oop_offset == 0 ) { // Undefined
3131 first_nonstatic_oop_offset = real_offset; 3131 first_nonstatic_oop_offset = real_offset;
3132 } 3132 }
3133 } 3133 }
3180 next_nonstatic_type_offset = align_size_up(notaligned_offset, wordSize ); 3180 next_nonstatic_type_offset = align_size_up(notaligned_offset, wordSize );
3181 instance_size = align_object_size(next_nonstatic_type_offset / wordSize); 3181 instance_size = align_object_size(next_nonstatic_type_offset / wordSize);
3182 3182
3183 assert(instance_size == align_object_size(align_size_up((instanceOopDesc::base_offset_in_bytes() + nonstatic_field_size*heapOopSize), wordSize) / wordSize), "consistent layout helper value"); 3183 assert(instance_size == align_object_size(align_size_up((instanceOopDesc::base_offset_in_bytes() + nonstatic_field_size*heapOopSize), wordSize) / wordSize), "consistent layout helper value");
3184 3184
3185 // Size of non-static oop map blocks (in words) allocated at end of klass 3185 // Number of non-static oop map blocks allocated at end of klass.
3186 int nonstatic_oop_map_size = compute_oop_map_size(super_klass, nonstatic_oop_map_count, first_nonstatic_oop_offset); 3186 int total_oop_map_count = compute_oop_map_count(super_klass,
3187 nonstatic_oop_map_count,
3188 first_nonstatic_oop_offset);
3187 3189
3188 // Compute reference type 3190 // Compute reference type
3189 ReferenceType rt; 3191 ReferenceType rt;
3190 if (super_klass() == NULL) { 3192 if (super_klass() == NULL) {
3191 rt = REF_NONE; 3193 rt = REF_NONE;
3194 } 3196 }
3195 3197
3196 // We can now create the basic klassOop for this klass 3198 // We can now create the basic klassOop for this klass
3197 klassOop ik = oopFactory::new_instanceKlass( 3199 klassOop ik = oopFactory::new_instanceKlass(
3198 vtable_size, itable_size, 3200 vtable_size, itable_size,
3199 static_field_size, nonstatic_oop_map_size, 3201 static_field_size, total_oop_map_count,
3200 rt, CHECK_(nullHandle)); 3202 rt, CHECK_(nullHandle));
3201 instanceKlassHandle this_klass (THREAD, ik); 3203 instanceKlassHandle this_klass (THREAD, ik);
3202 3204
3203 assert(this_klass->static_field_size() == static_field_size && 3205 assert(this_klass->static_field_size() == static_field_size, "sanity");
3204 this_klass->nonstatic_oop_map_size() == nonstatic_oop_map_size, "sanity check"); 3206 assert(this_klass->nonstatic_oop_map_count() == total_oop_map_count,
3207 "sanity");
3205 3208
3206 // Fill in information already parsed 3209 // Fill in information already parsed
3207 this_klass->set_access_flags(access_flags); 3210 this_klass->set_access_flags(access_flags);
3208 jint lh = Klass::instance_layout_helper(instance_size, false); 3211 jint lh = Klass::instance_layout_helper(instance_size, false);
3209 this_klass->set_layout_helper(lh); 3212 this_klass->set_layout_helper(lh);
3280 3283
3281 // Initialize itable offset tables 3284 // Initialize itable offset tables
3282 klassItable::setup_itable_offset_table(this_klass); 3285 klassItable::setup_itable_offset_table(this_klass);
3283 3286
3284 // Do final class setup 3287 // Do final class setup
3285 fill_oop_maps(this_klass, nonstatic_oop_map_count, nonstatic_oop_offsets, nonstatic_oop_length); 3288 fill_oop_maps(this_klass, nonstatic_oop_map_count, nonstatic_oop_offsets, nonstatic_oop_counts);
3286 3289
3287 set_precomputed_flags(this_klass); 3290 set_precomputed_flags(this_klass);
3288 3291
3289 // reinitialize modifiers, using the InnerClasses attribute 3292 // reinitialize modifiers, using the InnerClasses attribute
3290 int computed_modifiers = this_klass->compute_modifier_flags(CHECK_(nullHandle)); 3293 int computed_modifiers = this_klass->compute_modifier_flags(CHECK_(nullHandle));
3373 3376
3374 return this_klass; 3377 return this_klass;
3375 } 3378 }
3376 3379
3377 3380
3378 int ClassFileParser::compute_oop_map_size(instanceKlassHandle super, int nonstatic_oop_map_count, int first_nonstatic_oop_offset) { 3381 int ClassFileParser::compute_oop_map_count(instanceKlassHandle super,
3379 int map_size = super.is_null() ? 0 : super->nonstatic_oop_map_size(); 3382 int nonstatic_oop_map_count,
3383 int first_nonstatic_oop_offset) {
3384 int map_count = super.is_null() ? 0 : super->nonstatic_oop_map_count();
3380 if (nonstatic_oop_map_count > 0) { 3385 if (nonstatic_oop_map_count > 0) {
3381 // We have oops to add to map 3386 // We have oops to add to map
3382 if (map_size == 0) { 3387 if (map_count == 0) {
3383 map_size = nonstatic_oop_map_count; 3388 map_count = nonstatic_oop_map_count;
3384 } else { 3389 } else {
3385 // Check whether we should add a new map block or whether the last one can be extended 3390 // Check whether we should add a new map block or whether the last one can
3386 OopMapBlock* first_map = super->start_of_nonstatic_oop_maps(); 3391 // be extended
3387 OopMapBlock* last_map = first_map + map_size - 1; 3392 OopMapBlock* const first_map = super->start_of_nonstatic_oop_maps();
3388 3393 OopMapBlock* const last_map = first_map + map_count - 1;
3389 int next_offset = last_map->offset() + (last_map->length() * heapOopSize); 3394
3395 int next_offset = last_map->offset() + last_map->count() * heapOopSize;
3390 if (next_offset == first_nonstatic_oop_offset) { 3396 if (next_offset == first_nonstatic_oop_offset) {
3391 // There is no gap bettwen superklass's last oop field and first 3397 // There is no gap bettwen superklass's last oop field and first
3392 // local oop field, merge maps. 3398 // local oop field, merge maps.
3393 nonstatic_oop_map_count -= 1; 3399 nonstatic_oop_map_count -= 1;
3394 } else { 3400 } else {
3395 // Superklass didn't end with a oop field, add extra maps 3401 // Superklass didn't end with a oop field, add extra maps
3396 assert(next_offset<first_nonstatic_oop_offset, "just checking"); 3402 assert(next_offset < first_nonstatic_oop_offset, "just checking");
3397 } 3403 }
3398 map_size += nonstatic_oop_map_count; 3404 map_count += nonstatic_oop_map_count;
3399 } 3405 }
3400 } 3406 }
3401 return map_size; 3407 return map_count;
3402 } 3408 }
3403 3409
3404 3410
3405 void ClassFileParser::fill_oop_maps(instanceKlassHandle k, 3411 void ClassFileParser::fill_oop_maps(instanceKlassHandle k,
3406 int nonstatic_oop_map_count, 3412 int nonstatic_oop_map_count,
3407 u2* nonstatic_oop_offsets, u2* nonstatic_oop_length) { 3413 u2* nonstatic_oop_offsets,
3414 u2* nonstatic_oop_counts) {
3408 OopMapBlock* this_oop_map = k->start_of_nonstatic_oop_maps(); 3415 OopMapBlock* this_oop_map = k->start_of_nonstatic_oop_maps();
3409 OopMapBlock* last_oop_map = this_oop_map + k->nonstatic_oop_map_size(); 3416 const instanceKlass* const super = k->superklass();
3410 instanceKlass* super = k->superklass(); 3417 const int super_count = super != NULL ? super->nonstatic_oop_map_count() : 0;
3411 if (super != NULL) { 3418 if (super_count > 0) {
3412 int super_oop_map_size = super->nonstatic_oop_map_size(); 3419 // Copy maps from superklass
3413 OopMapBlock* super_oop_map = super->start_of_nonstatic_oop_maps(); 3420 OopMapBlock* super_oop_map = super->start_of_nonstatic_oop_maps();
3414 // Copy maps from superklass 3421 for (int i = 0; i < super_count; ++i) {
3415 while (super_oop_map_size-- > 0) {
3416 *this_oop_map++ = *super_oop_map++; 3422 *this_oop_map++ = *super_oop_map++;
3417 } 3423 }
3418 } 3424 }
3425
3419 if (nonstatic_oop_map_count > 0) { 3426 if (nonstatic_oop_map_count > 0) {
3420 if (this_oop_map + nonstatic_oop_map_count > last_oop_map) { 3427 if (super_count + nonstatic_oop_map_count > k->nonstatic_oop_map_count()) {
3421 // Calculated in compute_oop_map_size() number of oop maps is less then 3428 // The counts differ because there is no gap between superklass's last oop
3422 // collected oop maps since there is no gap between superklass's last oop 3429 // field and the first local oop field. Extend the last oop map copied
3423 // field and first local oop field. Extend the last oop map copied
3424 // from the superklass instead of creating new one. 3430 // from the superklass instead of creating new one.
3425 nonstatic_oop_map_count--; 3431 nonstatic_oop_map_count--;
3426 nonstatic_oop_offsets++; 3432 nonstatic_oop_offsets++;
3427 this_oop_map--; 3433 this_oop_map--;
3428 this_oop_map->set_length(this_oop_map->length() + *nonstatic_oop_length++); 3434 this_oop_map->set_count(this_oop_map->count() + *nonstatic_oop_counts++);
3429 this_oop_map++; 3435 this_oop_map++;
3430 } 3436 }
3431 assert((this_oop_map + nonstatic_oop_map_count) == last_oop_map, "just checking"); 3437
3432 // Add new map blocks, fill them 3438 // Add new map blocks, fill them
3433 while (nonstatic_oop_map_count-- > 0) { 3439 while (nonstatic_oop_map_count-- > 0) {
3434 this_oop_map->set_offset(*nonstatic_oop_offsets++); 3440 this_oop_map->set_offset(*nonstatic_oop_offsets++);
3435 this_oop_map->set_length(*nonstatic_oop_length++); 3441 this_oop_map->set_count(*nonstatic_oop_counts++);
3436 this_oop_map++; 3442 this_oop_map++;
3437 } 3443 }
3444 assert(k->start_of_nonstatic_oop_maps() + k->nonstatic_oop_map_count() ==
3445 this_oop_map, "sanity");
3438 } 3446 }
3439 } 3447 }
3440 3448
3441 3449
3442 void ClassFileParser::set_precomputed_flags(instanceKlassHandle k) { 3450 void ClassFileParser::set_precomputed_flags(instanceKlassHandle k) {