Mercurial > hg > truffle
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) { |