Mon, 14 Jan 2013 15:17:47 +0100
8003985: Support @Contended Annotation - JEP 142
Summary: HotSpot changes to support @Contended annotation.
Reviewed-by: coleenp, kvn, jrose
Contributed-by: Aleksey Shipilev <aleksey.shipilev@oracle.com>
1.1 --- a/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java Fri Jan 11 09:53:24 2013 -0800 1.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java Mon Jan 14 15:17:47 2013 +0100 1.3 @@ -52,6 +52,8 @@ 1.4 private static int LOW_OFFSET; 1.5 private static int HIGH_OFFSET; 1.6 private static int FIELD_SLOTS; 1.7 + private static short FIELDINFO_TAG_SIZE; 1.8 + private static short FIELDINFO_TAG_OFFSET; 1.9 1.10 // ClassState constants 1.11 private static int CLASS_STATE_ALLOCATED; 1.12 @@ -96,9 +98,12 @@ 1.13 NAME_INDEX_OFFSET = db.lookupIntConstant("FieldInfo::name_index_offset").intValue(); 1.14 SIGNATURE_INDEX_OFFSET = db.lookupIntConstant("FieldInfo::signature_index_offset").intValue(); 1.15 INITVAL_INDEX_OFFSET = db.lookupIntConstant("FieldInfo::initval_index_offset").intValue(); 1.16 - LOW_OFFSET = db.lookupIntConstant("FieldInfo::low_offset").intValue(); 1.17 - HIGH_OFFSET = db.lookupIntConstant("FieldInfo::high_offset").intValue(); 1.18 + LOW_OFFSET = db.lookupIntConstant("FieldInfo::low_packed_offset").intValue(); 1.19 + HIGH_OFFSET = db.lookupIntConstant("FieldInfo::high_packed_offset").intValue(); 1.20 FIELD_SLOTS = db.lookupIntConstant("FieldInfo::field_slots").intValue(); 1.21 + FIELDINFO_TAG_SIZE = db.lookupIntConstant("FIELDINFO_TAG_SIZE").shortValue(); 1.22 + FIELDINFO_TAG_OFFSET = db.lookupIntConstant("FIELDINFO_TAG_OFFSET").shortValue(); 1.23 + 1.24 // read ClassState constants 1.25 CLASS_STATE_ALLOCATED = db.lookupIntConstant("InstanceKlass::allocated").intValue(); 1.26 CLASS_STATE_LOADED = db.lookupIntConstant("InstanceKlass::loaded").intValue(); 1.27 @@ -314,8 +319,12 @@ 1.28 1.29 public int getFieldOffset(int index) { 1.30 U2Array fields = getFields(); 1.31 - return VM.getVM().buildIntFromShorts(fields.at(index * FIELD_SLOTS + LOW_OFFSET), 1.32 - fields.at(index * FIELD_SLOTS + HIGH_OFFSET)); 1.33 + short lo = fields.at(index * FIELD_SLOTS + LOW_OFFSET); 1.34 + short hi = fields.at(index * FIELD_SLOTS + HIGH_OFFSET); 1.35 + if ((lo & FIELDINFO_TAG_SIZE) == FIELDINFO_TAG_OFFSET) { 1.36 + return VM.getVM().buildIntFromShorts(lo, hi) >> FIELDINFO_TAG_SIZE; 1.37 + } 1.38 + throw new RuntimeException("should not reach here"); 1.39 } 1.40 1.41 // Accessors for declared fields
2.1 --- a/src/cpu/sparc/vm/vm_version_sparc.cpp Fri Jan 11 09:53:24 2013 -0800 2.2 +++ b/src/cpu/sparc/vm/vm_version_sparc.cpp Mon Jan 14 15:17:47 2013 +0100 2.3 @@ -259,6 +259,10 @@ 2.4 if (!has_vis1()) // Drop to 0 if no VIS1 support 2.5 UseVIS = 0; 2.6 2.7 + if (FLAG_IS_DEFAULT(ContendedPaddingWidth) && 2.8 + (cache_line_size > ContendedPaddingWidth)) 2.9 + ContendedPaddingWidth = cache_line_size; 2.10 + 2.11 #ifndef PRODUCT 2.12 if (PrintMiscellaneous && Verbose) { 2.13 tty->print("Allocation"); 2.14 @@ -286,6 +290,9 @@ 2.15 if (PrefetchFieldsAhead > 0) { 2.16 tty->print_cr("PrefetchFieldsAhead %d", PrefetchFieldsAhead); 2.17 } 2.18 + if (ContendedPaddingWidth > 0) { 2.19 + tty->print_cr("ContendedPaddingWidth %d", ContendedPaddingWidth); 2.20 + } 2.21 } 2.22 #endif // PRODUCT 2.23 }
3.1 --- a/src/cpu/x86/vm/vm_version_x86.cpp Fri Jan 11 09:53:24 2013 -0800 3.2 +++ b/src/cpu/x86/vm/vm_version_x86.cpp Mon Jan 14 15:17:47 2013 +0100 3.3 @@ -734,6 +734,10 @@ 3.4 PrefetchFieldsAhead = prefetch_fields_ahead(); 3.5 #endif 3.6 3.7 + if (FLAG_IS_DEFAULT(ContendedPaddingWidth) && 3.8 + (cache_line_size > ContendedPaddingWidth)) 3.9 + ContendedPaddingWidth = cache_line_size; 3.10 + 3.11 #ifndef PRODUCT 3.12 if (PrintMiscellaneous && Verbose) { 3.13 tty->print_cr("Logical CPUs per core: %u", 3.14 @@ -780,6 +784,9 @@ 3.15 if (PrefetchFieldsAhead > 0) { 3.16 tty->print_cr("PrefetchFieldsAhead %d", PrefetchFieldsAhead); 3.17 } 3.18 + if (ContendedPaddingWidth > 0) { 3.19 + tty->print_cr("ContendedPaddingWidth %d", ContendedPaddingWidth); 3.20 + } 3.21 } 3.22 #endif // !PRODUCT 3.23 }
4.1 --- a/src/share/vm/classfile/classFileParser.cpp Fri Jan 11 09:53:24 2013 -0800 4.2 +++ b/src/share/vm/classfile/classFileParser.cpp Mon Jan 14 15:17:47 2013 +0100 4.3 @@ -970,6 +970,12 @@ 4.4 runtime_visible_annotations_length = attribute_length; 4.5 runtime_visible_annotations = cfs->get_u1_buffer(); 4.6 assert(runtime_visible_annotations != NULL, "null visible annotations"); 4.7 + parse_annotations(loader_data, 4.8 + runtime_visible_annotations, 4.9 + runtime_visible_annotations_length, 4.10 + cp, 4.11 + parsed_annotations, 4.12 + CHECK); 4.13 cfs->skip_u1(runtime_visible_annotations_length, CHECK); 4.14 } else if (PreserveAllAnnotations && attribute_name == vmSymbols::tag_runtime_invisible_annotations()) { 4.15 runtime_invisible_annotations_length = attribute_length; 4.16 @@ -1216,19 +1222,16 @@ 4.17 field->initialize(access_flags.as_short(), 4.18 name_index, 4.19 signature_index, 4.20 - constantvalue_index, 4.21 - 0); 4.22 + constantvalue_index); 4.23 + BasicType type = cp->basic_type_for_signature_at(signature_index); 4.24 + 4.25 + // Remember how many oops we encountered and compute allocation type 4.26 + FieldAllocationType atype = fac->update(is_static, type); 4.27 + field->set_allocation_type(atype); 4.28 + 4.29 + // After field is initialized with type, we can augment it with aux info 4.30 if (parsed_annotations.has_any_annotations()) 4.31 parsed_annotations.apply_to(field); 4.32 - 4.33 - BasicType type = cp->basic_type_for_signature_at(signature_index); 4.34 - 4.35 - // Remember how many oops we encountered and compute allocation type 4.36 - FieldAllocationType atype = fac->update(is_static, type); 4.37 - 4.38 - // The correct offset is computed later (all oop fields will be located together) 4.39 - // We temporarily store the allocation type in the offset field 4.40 - field->set_offset(atype); 4.41 } 4.42 4.43 int index = length; 4.44 @@ -1259,17 +1262,13 @@ 4.45 field->initialize(JVM_ACC_FIELD_INTERNAL, 4.46 injected[n].name_index, 4.47 injected[n].signature_index, 4.48 - 0, 4.49 0); 4.50 4.51 BasicType type = FieldType::basic_type(injected[n].signature()); 4.52 4.53 // Remember how many oops we encountered and compute allocation type 4.54 FieldAllocationType atype = fac->update(false, type); 4.55 - 4.56 - // The correct offset is computed later (all oop fields will be located together) 4.57 - // We temporarily store the allocation type in the offset field 4.58 - field->set_offset(atype); 4.59 + field->set_allocation_type(atype); 4.60 index++; 4.61 } 4.62 } 4.63 @@ -1735,7 +1734,8 @@ 4.64 } 4.65 4.66 // Sift through annotations, looking for those significant to the VM: 4.67 -void ClassFileParser::parse_annotations(u1* buffer, int limit, 4.68 +void ClassFileParser::parse_annotations(ClassLoaderData* loader_data, 4.69 + u1* buffer, int limit, 4.70 constantPoolHandle cp, 4.71 ClassFileParser::AnnotationCollector* coll, 4.72 TRAPS) { 4.73 @@ -1752,9 +1752,12 @@ 4.74 e_type_off = 7, // utf8 such as 'Ljava/lang/annotation/RetentionPolicy;' 4.75 e_con_off = 9, // utf8 payload, such as 'SOURCE', 'CLASS', 'RUNTIME' 4.76 e_size = 11, // end of 'e' annotation 4.77 - c_tag_val = 'c', 4.78 - c_con_off = 7, // utf8 payload, such as 'I' or 'Ljava/lang/String;' 4.79 + c_tag_val = 'c', // payload is type 4.80 + c_con_off = 7, // utf8 payload, such as 'I' 4.81 c_size = 9, // end of 'c' annotation 4.82 + s_tag_val = 's', // payload is String 4.83 + s_con_off = 7, // utf8 payload, such as 'Ljava/lang/String;' 4.84 + s_size = 9, 4.85 min_size = 6 // smallest possible size (zero members) 4.86 }; 4.87 while ((--nann) >= 0 && (index-2 + min_size <= limit)) { 4.88 @@ -1773,57 +1776,65 @@ 4.89 } 4.90 4.91 // Here is where parsing particular annotations will take place. 4.92 - AnnotationCollector::ID id = coll->annotation_index(aname); 4.93 + AnnotationCollector::ID id = coll->annotation_index(loader_data, aname); 4.94 if (id == AnnotationCollector::_unknown) continue; 4.95 coll->set_annotation(id); 4.96 - // If there are no values, just set the bit and move on: 4.97 - if (count == 0) continue; 4.98 - 4.99 - // For the record, here is how annotation payloads can be collected. 4.100 - // Suppose we want to capture @Retention.value. Here is how: 4.101 - //if (id == AnnotationCollector::_class_Retention) { 4.102 - // Symbol* payload = NULL; 4.103 - // if (count == 1 4.104 - // && e_size == (index0 - index) // match size 4.105 - // && e_tag_val == *(abase + tag_off) 4.106 - // && (check_symbol_at(cp, Bytes::get_Java_u2(abase + e_type_off)) 4.107 - // == vmSymbols::RetentionPolicy_signature()) 4.108 - // && member == vmSymbols::value_name()) { 4.109 - // payload = check_symbol_at(cp, Bytes::get_Java_u2(abase + e_con_off)); 4.110 - // } 4.111 - // check_property(payload != NULL, 4.112 - // "Invalid @Retention annotation at offset %u in class file %s", 4.113 - // index0, CHECK); 4.114 - // if (payload != NULL) { 4.115 - // payload->increment_refcount(); 4.116 - // coll->_class_RetentionPolicy = payload; 4.117 - // } 4.118 - //} 4.119 + 4.120 + if (id == AnnotationCollector::_sun_misc_Contended) { 4.121 + if (count == 1 4.122 + && s_size == (index - index0) // match size 4.123 + && s_tag_val == *(abase + tag_off) 4.124 + && member == vmSymbols::value_name()) { 4.125 + u2 group_index = Bytes::get_Java_u2(abase + s_con_off); 4.126 + coll->set_contended_group(group_index); 4.127 + } else { 4.128 + coll->set_contended_group(0); // default contended group 4.129 + } 4.130 + coll->set_contended(true); 4.131 + } else { 4.132 + coll->set_contended(false); 4.133 + } 4.134 } 4.135 } 4.136 4.137 -ClassFileParser::AnnotationCollector::ID ClassFileParser::AnnotationCollector::annotation_index(Symbol* name) { 4.138 +ClassFileParser::AnnotationCollector::ID 4.139 +ClassFileParser::AnnotationCollector::annotation_index(ClassLoaderData* loader_data, 4.140 + Symbol* name) { 4.141 vmSymbols::SID sid = vmSymbols::find_sid(name); 4.142 + bool privileged = false; 4.143 + if (loader_data->is_the_null_class_loader_data()) { 4.144 + // Privileged code can use all annotations. Other code silently drops some. 4.145 + privileged = true; 4.146 + } 4.147 switch (sid) { 4.148 case vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_invoke_ForceInline_signature): 4.149 if (_location != _in_method) break; // only allow for methods 4.150 + if (!privileged) break; // only allow in privileged code 4.151 return _method_ForceInline; 4.152 case vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_invoke_DontInline_signature): 4.153 if (_location != _in_method) break; // only allow for methods 4.154 + if (!privileged) break; // only allow in privileged code 4.155 return _method_DontInline; 4.156 case vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_invoke_LambdaForm_Compiled_signature): 4.157 if (_location != _in_method) break; // only allow for methods 4.158 + if (!privileged) break; // only allow in privileged code 4.159 return _method_LambdaForm_Compiled; 4.160 case vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_invoke_LambdaForm_Hidden_signature): 4.161 if (_location != _in_method) break; // only allow for methods 4.162 + if (!privileged) break; // only allow in privileged code 4.163 return _method_LambdaForm_Hidden; 4.164 + case vmSymbols::VM_SYMBOL_ENUM_NAME(sun_misc_Contended_signature): 4.165 + if (_location != _in_field && _location != _in_class) break; // only allow for fields and classes 4.166 + if (!EnableContended || (RestrictContended && !privileged)) break; // honor privileges 4.167 + return _sun_misc_Contended; 4.168 default: break; 4.169 } 4.170 return AnnotationCollector::_unknown; 4.171 } 4.172 4.173 void ClassFileParser::FieldAnnotationCollector::apply_to(FieldInfo* f) { 4.174 - fatal("no field annotations yet"); 4.175 + if (is_contended()) 4.176 + f->set_contended_group(contended_group()); 4.177 } 4.178 4.179 void ClassFileParser::MethodAnnotationCollector::apply_to(methodHandle m) { 4.180 @@ -1838,7 +1849,7 @@ 4.181 } 4.182 4.183 void ClassFileParser::ClassAnnotationCollector::apply_to(instanceKlassHandle k) { 4.184 - fatal("no class annotations yet"); 4.185 + k->set_is_contended(is_contended()); 4.186 } 4.187 4.188 4.189 @@ -2181,7 +2192,8 @@ 4.190 runtime_visible_annotations_length = method_attribute_length; 4.191 runtime_visible_annotations = cfs->get_u1_buffer(); 4.192 assert(runtime_visible_annotations != NULL, "null visible annotations"); 4.193 - parse_annotations(runtime_visible_annotations, 4.194 + parse_annotations(loader_data, 4.195 + runtime_visible_annotations, 4.196 runtime_visible_annotations_length, cp, &parsed_annotations, 4.197 CHECK_(nullHandle)); 4.198 cfs->skip_u1(runtime_visible_annotations_length, CHECK_(nullHandle)); 4.199 @@ -2886,7 +2898,8 @@ 4.200 runtime_visible_annotations_length = attribute_length; 4.201 runtime_visible_annotations = cfs->get_u1_buffer(); 4.202 assert(runtime_visible_annotations != NULL, "null visible annotations"); 4.203 - parse_annotations(runtime_visible_annotations, 4.204 + parse_annotations(loader_data, 4.205 + runtime_visible_annotations, 4.206 runtime_visible_annotations_length, 4.207 cp, 4.208 parsed_annotations, 4.209 @@ -3405,18 +3418,21 @@ 4.210 // Size of Java itable (in words) 4.211 itable_size = access_flags.is_interface() ? 0 : klassItable::compute_itable_size(transitive_interfaces); 4.212 4.213 + // get the padding width from the option 4.214 + // TODO: Ask VM about specific CPU we are running on 4.215 + int pad_size = ContendedPaddingWidth; 4.216 + 4.217 // Field size and offset computation 4.218 int nonstatic_field_size = super_klass() == NULL ? 0 : super_klass->nonstatic_field_size(); 4.219 #ifndef PRODUCT 4.220 int orig_nonstatic_field_size = 0; 4.221 #endif 4.222 - int static_field_size = 0; 4.223 int next_static_oop_offset; 4.224 int next_static_double_offset; 4.225 int next_static_word_offset; 4.226 int next_static_short_offset; 4.227 int next_static_byte_offset; 4.228 - int next_static_type_offset; 4.229 + int next_static_padded_offset; 4.230 int next_nonstatic_oop_offset; 4.231 int next_nonstatic_double_offset; 4.232 int next_nonstatic_word_offset; 4.233 @@ -3426,11 +3442,36 @@ 4.234 int first_nonstatic_oop_offset; 4.235 int first_nonstatic_field_offset; 4.236 int next_nonstatic_field_offset; 4.237 + int next_nonstatic_padded_offset; 4.238 + 4.239 + // Count the contended fields by type. 4.240 + int static_contended_count = 0; 4.241 + int nonstatic_contended_count = 0; 4.242 + FieldAllocationCount fac_contended; 4.243 + for (AllFieldStream fs(fields, cp); !fs.done(); fs.next()) { 4.244 + FieldAllocationType atype = (FieldAllocationType) fs.allocation_type(); 4.245 + if (fs.is_contended()) { 4.246 + fac_contended.count[atype]++; 4.247 + if (fs.access_flags().is_static()) { 4.248 + static_contended_count++; 4.249 + } else { 4.250 + nonstatic_contended_count++; 4.251 + } 4.252 + } 4.253 + } 4.254 + int contended_count = static_contended_count + nonstatic_contended_count; 4.255 + 4.256 4.257 // Calculate the starting byte offsets 4.258 next_static_oop_offset = InstanceMirrorKlass::offset_of_static_fields(); 4.259 + 4.260 + // class is contended, pad before all the fields 4.261 + if (parsed_annotations.is_contended()) { 4.262 + next_static_oop_offset += pad_size; 4.263 + } 4.264 + 4.265 next_static_double_offset = next_static_oop_offset + 4.266 - (fac.count[STATIC_OOP] * heapOopSize); 4.267 + ((fac.count[STATIC_OOP] - fac_contended.count[STATIC_OOP]) * heapOopSize); 4.268 if ( fac.count[STATIC_DOUBLE] && 4.269 (Universe::field_type_should_be_aligned(T_DOUBLE) || 4.270 Universe::field_type_should_be_aligned(T_LONG)) ) { 4.271 @@ -3438,25 +3479,29 @@ 4.272 } 4.273 4.274 next_static_word_offset = next_static_double_offset + 4.275 - (fac.count[STATIC_DOUBLE] * BytesPerLong); 4.276 + ((fac.count[STATIC_DOUBLE] - fac_contended.count[STATIC_DOUBLE]) * BytesPerLong); 4.277 next_static_short_offset = next_static_word_offset + 4.278 - (fac.count[STATIC_WORD] * BytesPerInt); 4.279 + ((fac.count[STATIC_WORD] - fac_contended.count[STATIC_WORD]) * BytesPerInt); 4.280 next_static_byte_offset = next_static_short_offset + 4.281 - (fac.count[STATIC_SHORT] * BytesPerShort); 4.282 - next_static_type_offset = align_size_up((next_static_byte_offset + 4.283 - fac.count[STATIC_BYTE] ), wordSize ); 4.284 - static_field_size = (next_static_type_offset - 4.285 - next_static_oop_offset) / wordSize; 4.286 + ((fac.count[STATIC_SHORT] - fac_contended.count[STATIC_SHORT]) * BytesPerShort); 4.287 + next_static_padded_offset = next_static_byte_offset + 4.288 + ((fac.count[STATIC_BYTE] - fac_contended.count[STATIC_BYTE]) * 1); 4.289 4.290 first_nonstatic_field_offset = instanceOopDesc::base_offset_in_bytes() + 4.291 nonstatic_field_size * heapOopSize; 4.292 + 4.293 + // class is contended, pad before all the fields 4.294 + if (parsed_annotations.is_contended()) { 4.295 + first_nonstatic_field_offset += pad_size; 4.296 + } 4.297 + 4.298 next_nonstatic_field_offset = first_nonstatic_field_offset; 4.299 4.300 - unsigned int nonstatic_double_count = fac.count[NONSTATIC_DOUBLE]; 4.301 - unsigned int nonstatic_word_count = fac.count[NONSTATIC_WORD]; 4.302 - unsigned int nonstatic_short_count = fac.count[NONSTATIC_SHORT]; 4.303 - unsigned int nonstatic_byte_count = fac.count[NONSTATIC_BYTE]; 4.304 - unsigned int nonstatic_oop_count = fac.count[NONSTATIC_OOP]; 4.305 + unsigned int nonstatic_double_count = fac.count[NONSTATIC_DOUBLE] - fac_contended.count[NONSTATIC_DOUBLE]; 4.306 + unsigned int nonstatic_word_count = fac.count[NONSTATIC_WORD] - fac_contended.count[NONSTATIC_WORD]; 4.307 + unsigned int nonstatic_short_count = fac.count[NONSTATIC_SHORT] - fac_contended.count[NONSTATIC_SHORT]; 4.308 + unsigned int nonstatic_byte_count = fac.count[NONSTATIC_BYTE] - fac_contended.count[NONSTATIC_BYTE]; 4.309 + unsigned int nonstatic_oop_count = fac.count[NONSTATIC_OOP] - fac_contended.count[NONSTATIC_OOP]; 4.310 4.311 bool super_has_nonstatic_fields = 4.312 (super_klass() != NULL && super_klass->has_nonstatic_fields()); 4.313 @@ -3529,12 +3574,12 @@ 4.314 } 4.315 4.316 if( allocation_style == 0 ) { 4.317 - // Fields order: oops, longs/doubles, ints, shorts/chars, bytes 4.318 + // Fields order: oops, longs/doubles, ints, shorts/chars, bytes, padded fields 4.319 next_nonstatic_oop_offset = next_nonstatic_field_offset; 4.320 next_nonstatic_double_offset = next_nonstatic_oop_offset + 4.321 (nonstatic_oop_count * heapOopSize); 4.322 } else if( allocation_style == 1 ) { 4.323 - // Fields order: longs/doubles, ints, shorts/chars, bytes, oops 4.324 + // Fields order: longs/doubles, ints, shorts/chars, bytes, oops, padded fields 4.325 next_nonstatic_double_offset = next_nonstatic_field_offset; 4.326 } else if( allocation_style == 2 ) { 4.327 // Fields allocation: oops fields in super and sub classes are together. 4.328 @@ -3613,27 +3658,33 @@ 4.329 (nonstatic_word_count * BytesPerInt); 4.330 next_nonstatic_byte_offset = next_nonstatic_short_offset + 4.331 (nonstatic_short_count * BytesPerShort); 4.332 - 4.333 - int notaligned_offset; 4.334 - if( allocation_style == 0 ) { 4.335 - notaligned_offset = next_nonstatic_byte_offset + nonstatic_byte_count; 4.336 - } else { // allocation_style == 1 4.337 - next_nonstatic_oop_offset = next_nonstatic_byte_offset + nonstatic_byte_count; 4.338 + next_nonstatic_padded_offset = next_nonstatic_byte_offset + 4.339 + nonstatic_byte_count; 4.340 + 4.341 + // let oops jump before padding with this allocation style 4.342 + if( allocation_style == 1 ) { 4.343 + next_nonstatic_oop_offset = next_nonstatic_padded_offset; 4.344 if( nonstatic_oop_count > 0 ) { 4.345 next_nonstatic_oop_offset = align_size_up(next_nonstatic_oop_offset, heapOopSize); 4.346 } 4.347 - notaligned_offset = next_nonstatic_oop_offset + (nonstatic_oop_count * heapOopSize); 4.348 + next_nonstatic_padded_offset = next_nonstatic_oop_offset + (nonstatic_oop_count * heapOopSize); 4.349 } 4.350 - next_nonstatic_type_offset = align_size_up(notaligned_offset, heapOopSize ); 4.351 - nonstatic_field_size = nonstatic_field_size + ((next_nonstatic_type_offset 4.352 - - first_nonstatic_field_offset)/heapOopSize); 4.353 4.354 // Iterate over fields again and compute correct offsets. 4.355 // The field allocation type was temporarily stored in the offset slot. 4.356 // oop fields are located before non-oop fields (static and non-static). 4.357 for (AllFieldStream fs(fields, cp); !fs.done(); fs.next()) { 4.358 + 4.359 + // skip already laid out fields 4.360 + if (fs.is_offset_set()) continue; 4.361 + 4.362 + // contended fields are handled below 4.363 + if (fs.is_contended()) continue; 4.364 + 4.365 int real_offset; 4.366 - FieldAllocationType atype = (FieldAllocationType) fs.offset(); 4.367 + FieldAllocationType atype = (FieldAllocationType) fs.allocation_type(); 4.368 + 4.369 + // pack the rest of the fields 4.370 switch (atype) { 4.371 case STATIC_OOP: 4.372 real_offset = next_static_oop_offset; 4.373 @@ -3722,13 +3773,225 @@ 4.374 fs.set_offset(real_offset); 4.375 } 4.376 4.377 + 4.378 + // Handle the contended cases. 4.379 + // 4.380 + // Each contended field should not intersect the cache line with another contended field. 4.381 + // In the absence of alignment information, we end up with pessimistically separating 4.382 + // the fields with full-width padding. 4.383 + // 4.384 + // Additionally, this should not break alignment for the fields, so we round the alignment up 4.385 + // for each field. 4.386 + if (contended_count > 0) { 4.387 + 4.388 + // if there is at least one contended field, we need to have pre-padding for them 4.389 + if (nonstatic_contended_count > 0) { 4.390 + next_nonstatic_padded_offset += pad_size; 4.391 + } 4.392 + 4.393 + // collect all contended groups 4.394 + BitMap bm(cp->size()); 4.395 + for (AllFieldStream fs(fields, cp); !fs.done(); fs.next()) { 4.396 + // skip already laid out fields 4.397 + if (fs.is_offset_set()) continue; 4.398 + 4.399 + if (fs.is_contended()) { 4.400 + bm.set_bit(fs.contended_group()); 4.401 + } 4.402 + } 4.403 + 4.404 + int current_group = -1; 4.405 + while ((current_group = (int)bm.get_next_one_offset(current_group + 1)) != (int)bm.size()) { 4.406 + 4.407 + for (AllFieldStream fs(fields, cp); !fs.done(); fs.next()) { 4.408 + 4.409 + // skip already laid out fields 4.410 + if (fs.is_offset_set()) continue; 4.411 + 4.412 + // skip non-contended fields and fields from different group 4.413 + if (!fs.is_contended() || (fs.contended_group() != current_group)) continue; 4.414 + 4.415 + // handle statics below 4.416 + if (fs.access_flags().is_static()) continue; 4.417 + 4.418 + int real_offset; 4.419 + FieldAllocationType atype = (FieldAllocationType) fs.allocation_type(); 4.420 + 4.421 + switch (atype) { 4.422 + case NONSTATIC_BYTE: 4.423 + next_nonstatic_padded_offset = align_size_up(next_nonstatic_padded_offset, 1); 4.424 + real_offset = next_nonstatic_padded_offset; 4.425 + next_nonstatic_padded_offset += 1; 4.426 + break; 4.427 + 4.428 + case NONSTATIC_SHORT: 4.429 + next_nonstatic_padded_offset = align_size_up(next_nonstatic_padded_offset, BytesPerShort); 4.430 + real_offset = next_nonstatic_padded_offset; 4.431 + next_nonstatic_padded_offset += BytesPerShort; 4.432 + break; 4.433 + 4.434 + case NONSTATIC_WORD: 4.435 + next_nonstatic_padded_offset = align_size_up(next_nonstatic_padded_offset, BytesPerInt); 4.436 + real_offset = next_nonstatic_padded_offset; 4.437 + next_nonstatic_padded_offset += BytesPerInt; 4.438 + break; 4.439 + 4.440 + case NONSTATIC_DOUBLE: 4.441 + next_nonstatic_padded_offset = align_size_up(next_nonstatic_padded_offset, BytesPerLong); 4.442 + real_offset = next_nonstatic_padded_offset; 4.443 + next_nonstatic_padded_offset += BytesPerLong; 4.444 + break; 4.445 + 4.446 + case NONSTATIC_OOP: 4.447 + next_nonstatic_padded_offset = align_size_up(next_nonstatic_padded_offset, heapOopSize); 4.448 + real_offset = next_nonstatic_padded_offset; 4.449 + next_nonstatic_padded_offset += heapOopSize; 4.450 + 4.451 + // Create new oop map 4.452 + nonstatic_oop_offsets[nonstatic_oop_map_count] = real_offset; 4.453 + nonstatic_oop_counts [nonstatic_oop_map_count] = 1; 4.454 + nonstatic_oop_map_count += 1; 4.455 + if( first_nonstatic_oop_offset == 0 ) { // Undefined 4.456 + first_nonstatic_oop_offset = real_offset; 4.457 + } 4.458 + break; 4.459 + 4.460 + default: 4.461 + ShouldNotReachHere(); 4.462 + } 4.463 + 4.464 + if (fs.contended_group() == 0) { 4.465 + // Contended group defines the equivalence class over the fields: 4.466 + // the fields within the same contended group are not inter-padded. 4.467 + // The only exception is default group, which does not incur the 4.468 + // equivalence, and so requires intra-padding. 4.469 + next_nonstatic_padded_offset += pad_size; 4.470 + } 4.471 + 4.472 + fs.set_offset(real_offset); 4.473 + } // for 4.474 + 4.475 + // Start laying out the next group. 4.476 + // Note that this will effectively pad the last group in the back; 4.477 + // this is expected to alleviate memory contention effects for 4.478 + // subclass fields and/or adjacent object. 4.479 + // If this was the default group, the padding is already in place. 4.480 + if (current_group != 0) { 4.481 + next_nonstatic_padded_offset += pad_size; 4.482 + } 4.483 + } 4.484 + 4.485 + // handle static fields 4.486 + 4.487 + // if there is at least one contended field, we need to have pre-padding for them 4.488 + if (static_contended_count > 0) { 4.489 + next_static_padded_offset += pad_size; 4.490 + } 4.491 + 4.492 + current_group = -1; 4.493 + while ((current_group = (int)bm.get_next_one_offset(current_group + 1)) != (int)bm.size()) { 4.494 + 4.495 + for (AllFieldStream fs(fields, cp); !fs.done(); fs.next()) { 4.496 + 4.497 + // skip already laid out fields 4.498 + if (fs.is_offset_set()) continue; 4.499 + 4.500 + // skip non-contended fields and fields from different group 4.501 + if (!fs.is_contended() || (fs.contended_group() != current_group)) continue; 4.502 + 4.503 + // non-statics already handled above 4.504 + if (!fs.access_flags().is_static()) continue; 4.505 + 4.506 + int real_offset; 4.507 + FieldAllocationType atype = (FieldAllocationType) fs.allocation_type(); 4.508 + 4.509 + switch (atype) { 4.510 + 4.511 + case STATIC_BYTE: 4.512 + next_static_padded_offset = align_size_up(next_static_padded_offset, 1); 4.513 + real_offset = next_static_padded_offset; 4.514 + next_static_padded_offset += 1; 4.515 + break; 4.516 + 4.517 + case STATIC_SHORT: 4.518 + next_static_padded_offset = align_size_up(next_static_padded_offset, BytesPerShort); 4.519 + real_offset = next_static_padded_offset; 4.520 + next_static_padded_offset += BytesPerShort; 4.521 + break; 4.522 + 4.523 + case STATIC_WORD: 4.524 + next_static_padded_offset = align_size_up(next_static_padded_offset, BytesPerInt); 4.525 + real_offset = next_static_padded_offset; 4.526 + next_static_padded_offset += BytesPerInt; 4.527 + break; 4.528 + 4.529 + case STATIC_DOUBLE: 4.530 + next_static_padded_offset = align_size_up(next_static_padded_offset, BytesPerLong); 4.531 + real_offset = next_static_padded_offset; 4.532 + next_static_padded_offset += BytesPerLong; 4.533 + break; 4.534 + 4.535 + case STATIC_OOP: 4.536 + next_static_padded_offset = align_size_up(next_static_padded_offset, heapOopSize); 4.537 + real_offset = next_static_padded_offset; 4.538 + next_static_padded_offset += heapOopSize; 4.539 + break; 4.540 + 4.541 + default: 4.542 + ShouldNotReachHere(); 4.543 + } 4.544 + 4.545 + if (fs.contended_group() == 0) { 4.546 + // Contended group defines the equivalence class over the fields: 4.547 + // the fields within the same contended group are not inter-padded. 4.548 + // The only exception is default group, which does not incur the 4.549 + // equivalence, and so requires intra-padding. 4.550 + next_static_padded_offset += pad_size; 4.551 + } 4.552 + 4.553 + fs.set_offset(real_offset); 4.554 + } // for 4.555 + 4.556 + // Start laying out the next group. 4.557 + // Note that this will effectively pad the last group in the back; 4.558 + // this is expected to alleviate memory contention effects for 4.559 + // subclass fields and/or adjacent object. 4.560 + // If this was the default group, the padding is already in place. 4.561 + if (current_group != 0) { 4.562 + next_static_padded_offset += pad_size; 4.563 + } 4.564 + 4.565 + } 4.566 + 4.567 + } // handle contended 4.568 + 4.569 // Size of instances 4.570 int instance_size; 4.571 4.572 + int notaligned_offset = next_nonstatic_padded_offset; 4.573 + 4.574 + // Entire class is contended, pad in the back. 4.575 + // This helps to alleviate memory contention effects for subclass fields 4.576 + // and/or adjacent object. 4.577 + if (parsed_annotations.is_contended()) { 4.578 + notaligned_offset += pad_size; 4.579 + next_static_padded_offset += pad_size; 4.580 + } 4.581 + 4.582 + int next_static_type_offset = align_size_up(next_static_padded_offset, wordSize); 4.583 + int static_field_size = (next_static_type_offset - 4.584 + InstanceMirrorKlass::offset_of_static_fields()) / wordSize; 4.585 + 4.586 + next_nonstatic_type_offset = align_size_up(notaligned_offset, heapOopSize ); 4.587 + nonstatic_field_size = nonstatic_field_size + ((next_nonstatic_type_offset 4.588 + - first_nonstatic_field_offset)/heapOopSize); 4.589 + 4.590 next_nonstatic_type_offset = align_size_up(notaligned_offset, wordSize ); 4.591 instance_size = align_object_size(next_nonstatic_type_offset / wordSize); 4.592 4.593 - assert(instance_size == align_object_size(align_size_up((instanceOopDesc::base_offset_in_bytes() + nonstatic_field_size*heapOopSize), wordSize) / wordSize), "consistent layout helper value"); 4.594 + assert(instance_size == align_object_size(align_size_up( 4.595 + (instanceOopDesc::base_offset_in_bytes() + nonstatic_field_size*heapOopSize + ((parsed_annotations.is_contended()) ? pad_size : 0)), 4.596 + wordSize) / wordSize), "consistent layout helper value"); 4.597 4.598 // Number of non-static oop map blocks allocated at end of klass. 4.599 const unsigned int total_oop_map_count = 4.600 @@ -4008,6 +4271,18 @@ 4.601 } 4.602 #endif 4.603 4.604 +#ifndef PRODUCT 4.605 + if (PrintFieldLayout) { 4.606 + print_field_layout(name, 4.607 + fields, 4.608 + cp, 4.609 + instance_size, 4.610 + first_nonstatic_field_offset, 4.611 + next_nonstatic_field_offset, 4.612 + next_static_type_offset); 4.613 + } 4.614 +#endif 4.615 + 4.616 // preserve result across HandleMark 4.617 preserve_this_klass = this_klass(); 4.618 } 4.619 @@ -4020,6 +4295,38 @@ 4.620 return this_klass; 4.621 } 4.622 4.623 +void ClassFileParser::print_field_layout(Symbol* name, 4.624 + Array<u2>* fields, 4.625 + constantPoolHandle cp, 4.626 + int instance_size, 4.627 + int instance_fields_start, 4.628 + int instance_fields_end, 4.629 + int static_fields_end) { 4.630 + tty->print("%s: field layout\n", name->as_klass_external_name()); 4.631 + tty->print(" @%3d %s\n", instance_fields_start, "--- instance fields start ---"); 4.632 + for (AllFieldStream fs(fields, cp); !fs.done(); fs.next()) { 4.633 + if (!fs.access_flags().is_static()) { 4.634 + tty->print(" @%3d \"%s\" %s\n", 4.635 + fs.offset(), 4.636 + fs.name()->as_klass_external_name(), 4.637 + fs.signature()->as_klass_external_name()); 4.638 + } 4.639 + } 4.640 + tty->print(" @%3d %s\n", instance_fields_end, "--- instance fields end ---"); 4.641 + tty->print(" @%3d %s\n", instance_size * wordSize, "--- instance ends ---"); 4.642 + tty->print(" @%3d %s\n", InstanceMirrorKlass::offset_of_static_fields(), "--- static fields start ---"); 4.643 + for (AllFieldStream fs(fields, cp); !fs.done(); fs.next()) { 4.644 + if (fs.access_flags().is_static()) { 4.645 + tty->print(" @%3d \"%s\" %s\n", 4.646 + fs.offset(), 4.647 + fs.name()->as_klass_external_name(), 4.648 + fs.signature()->as_klass_external_name()); 4.649 + } 4.650 + } 4.651 + tty->print(" @%3d %s\n", static_fields_end, "--- static fields end ---"); 4.652 + tty->print("\n"); 4.653 +} 4.654 + 4.655 unsigned int 4.656 ClassFileParser::compute_oop_map_count(instanceKlassHandle super, 4.657 unsigned int nonstatic_oop_map_count,
5.1 --- a/src/share/vm/classfile/classFileParser.hpp Fri Jan 11 09:53:24 2013 -0800 5.2 +++ b/src/share/vm/classfile/classFileParser.hpp Mon Jan 14 15:17:47 2013 +0100 5.3 @@ -95,17 +95,20 @@ 5.4 _method_DontInline, 5.5 _method_LambdaForm_Compiled, 5.6 _method_LambdaForm_Hidden, 5.7 + _sun_misc_Contended, 5.8 _annotation_LIMIT 5.9 }; 5.10 const Location _location; 5.11 int _annotations_present; 5.12 + u2 _contended_group; 5.13 + 5.14 AnnotationCollector(Location location) 5.15 : _location(location), _annotations_present(0) 5.16 { 5.17 assert((int)_annotation_LIMIT <= (int)sizeof(_annotations_present) * BitsPerByte, ""); 5.18 } 5.19 // If this annotation name has an ID, report it (or _none). 5.20 - ID annotation_index(Symbol* name); 5.21 + ID annotation_index(ClassLoaderData* loader_data, Symbol* name); 5.22 // Set the annotation name: 5.23 void set_annotation(ID id) { 5.24 assert((int)id >= 0 && (int)id < (int)_annotation_LIMIT, "oob"); 5.25 @@ -114,6 +117,12 @@ 5.26 // Report if the annotation is present. 5.27 bool has_any_annotations() { return _annotations_present != 0; } 5.28 bool has_annotation(ID id) { return (nth_bit((int)id) & _annotations_present) != 0; } 5.29 + 5.30 + void set_contended_group(u2 group) { _contended_group = group; } 5.31 + u2 contended_group() { return _contended_group; } 5.32 + 5.33 + void set_contended(bool contended) { set_annotation(_sun_misc_Contended); } 5.34 + bool is_contended() { return has_annotation(_sun_misc_Contended); } 5.35 }; 5.36 class FieldAnnotationCollector: public AnnotationCollector { 5.37 public: 5.38 @@ -177,6 +186,14 @@ 5.39 Array<AnnotationArray*>** fields_type_annotations, 5.40 u2* java_fields_count_ptr, TRAPS); 5.41 5.42 + void print_field_layout(Symbol* name, 5.43 + Array<u2>* fields, 5.44 + constantPoolHandle cp, 5.45 + int instance_size, 5.46 + int instance_fields_start, 5.47 + int instance_fields_end, 5.48 + int static_fields_end); 5.49 + 5.50 // Method parsing 5.51 methodHandle parse_method(ClassLoaderData* loader_data, 5.52 constantPoolHandle cp, 5.53 @@ -247,7 +264,8 @@ 5.54 int runtime_invisible_annotations_length, TRAPS); 5.55 int skip_annotation(u1* buffer, int limit, int index); 5.56 int skip_annotation_value(u1* buffer, int limit, int index); 5.57 - void parse_annotations(u1* buffer, int limit, constantPoolHandle cp, 5.58 + void parse_annotations(ClassLoaderData* loader_data, 5.59 + u1* buffer, int limit, constantPoolHandle cp, 5.60 /* Results (currently, only one result is supported): */ 5.61 AnnotationCollector* result, 5.62 TRAPS);
6.1 --- a/src/share/vm/classfile/vmSymbols.hpp Fri Jan 11 09:53:24 2013 -0800 6.2 +++ b/src/share/vm/classfile/vmSymbols.hpp Mon Jan 14 15:17:47 2013 +0100 6.3 @@ -194,7 +194,10 @@ 6.4 template(java_lang_VirtualMachineError, "java/lang/VirtualMachineError") \ 6.5 template(java_lang_StackOverflowError, "java/lang/StackOverflowError") \ 6.6 template(java_lang_StackTraceElement, "java/lang/StackTraceElement") \ 6.7 + \ 6.8 + /* Concurrency support */ \ 6.9 template(java_util_concurrent_locks_AbstractOwnableSynchronizer, "java/util/concurrent/locks/AbstractOwnableSynchronizer") \ 6.10 + template(sun_misc_Contended_signature, "Lsun/misc/Contended;") \ 6.11 \ 6.12 /* class symbols needed by intrinsics */ \ 6.13 VM_INTRINSICS_DO(VM_INTRINSIC_IGNORE, template, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE) \ 6.14 @@ -284,7 +287,7 @@ 6.15 NOT_LP64( do_alias(intptr_signature, int_signature) ) \ 6.16 LP64_ONLY( do_alias(intptr_signature, long_signature) ) \ 6.17 template(selectAlternative_signature, "(ZLjava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;)Ljava/lang/invoke/MethodHandle;") \ 6.18 - \ 6.19 + \ 6.20 /* common method and field names */ \ 6.21 template(object_initializer_name, "<init>") \ 6.22 template(class_initializer_name, "<clinit>") \
7.1 --- a/src/share/vm/oops/fieldInfo.hpp Fri Jan 11 09:53:24 2013 -0800 7.2 +++ b/src/share/vm/oops/fieldInfo.hpp Mon Jan 14 15:17:47 2013 +0100 7.3 @@ -43,14 +43,29 @@ 7.4 public: 7.5 // fields 7.6 // Field info extracted from the class file and stored 7.7 - // as an array of 7 shorts 7.8 + // as an array of 6 shorts. 7.9 + 7.10 +#define FIELDINFO_TAG_SIZE 2 7.11 +#define FIELDINFO_TAG_BLANK 0 7.12 +#define FIELDINFO_TAG_OFFSET 1 7.13 +#define FIELDINFO_TAG_TYPE_PLAIN 2 7.14 +#define FIELDINFO_TAG_TYPE_CONTENDED 3 7.15 +#define FIELDINFO_TAG_MASK 3 7.16 + 7.17 + // Packed field has the tag, and can be either of: 7.18 + // hi bits <--------------------------- lo bits 7.19 + // |---------high---------|---------low---------| 7.20 + // ..........................................00 - blank 7.21 + // [------------------offset----------------]01 - real field offset 7.22 + // ......................[-------type-------]10 - plain field with type 7.23 + // [--contention_group--][-------type-------]11 - contended field with type and contention group 7.24 enum FieldOffset { 7.25 access_flags_offset = 0, 7.26 name_index_offset = 1, 7.27 signature_index_offset = 2, 7.28 initval_index_offset = 3, 7.29 - low_offset = 4, 7.30 - high_offset = 5, 7.31 + low_packed_offset = 4, 7.32 + high_packed_offset = 5, 7.33 field_slots = 6 7.34 }; 7.35 7.36 @@ -76,17 +91,90 @@ 7.37 void initialize(u2 access_flags, 7.38 u2 name_index, 7.39 u2 signature_index, 7.40 - u2 initval_index, 7.41 - u4 offset) { 7.42 + u2 initval_index) { 7.43 _shorts[access_flags_offset] = access_flags; 7.44 _shorts[name_index_offset] = name_index; 7.45 _shorts[signature_index_offset] = signature_index; 7.46 _shorts[initval_index_offset] = initval_index; 7.47 - set_offset(offset); 7.48 + _shorts[low_packed_offset] = 0; 7.49 + _shorts[high_packed_offset] = 0; 7.50 } 7.51 7.52 u2 access_flags() const { return _shorts[access_flags_offset]; } 7.53 - u4 offset() const { return build_int_from_shorts(_shorts[low_offset], _shorts[high_offset]); } 7.54 + u4 offset() const { 7.55 + u2 lo = _shorts[low_packed_offset]; 7.56 + switch(lo & FIELDINFO_TAG_MASK) { 7.57 + case FIELDINFO_TAG_OFFSET: 7.58 + return build_int_from_shorts(_shorts[low_packed_offset], _shorts[high_packed_offset]) >> FIELDINFO_TAG_SIZE; 7.59 +#ifndef PRODUCT 7.60 + case FIELDINFO_TAG_TYPE_PLAIN: 7.61 + ShouldNotReachHere2("Asking offset for the plain type field"); 7.62 + case FIELDINFO_TAG_TYPE_CONTENDED: 7.63 + ShouldNotReachHere2("Asking offset for the contended type field"); 7.64 + case FIELDINFO_TAG_BLANK: 7.65 + ShouldNotReachHere2("Asking offset for the blank field"); 7.66 +#endif 7.67 + } 7.68 + ShouldNotReachHere(); 7.69 + return 0; 7.70 + } 7.71 + 7.72 + bool is_contended() const { 7.73 + u2 lo = _shorts[low_packed_offset]; 7.74 + switch(lo & FIELDINFO_TAG_MASK) { 7.75 + case FIELDINFO_TAG_TYPE_PLAIN: 7.76 + return false; 7.77 + case FIELDINFO_TAG_TYPE_CONTENDED: 7.78 + return true; 7.79 +#ifndef PRODUCT 7.80 + case FIELDINFO_TAG_OFFSET: 7.81 + ShouldNotReachHere2("Asking contended flag for the field with offset"); 7.82 + case FIELDINFO_TAG_BLANK: 7.83 + ShouldNotReachHere2("Asking contended flag for the blank field"); 7.84 +#endif 7.85 + } 7.86 + ShouldNotReachHere(); 7.87 + return false; 7.88 + } 7.89 + 7.90 + u2 contended_group() const { 7.91 + u2 lo = _shorts[low_packed_offset]; 7.92 + switch(lo & FIELDINFO_TAG_MASK) { 7.93 + case FIELDINFO_TAG_TYPE_PLAIN: 7.94 + return 0; 7.95 + case FIELDINFO_TAG_TYPE_CONTENDED: 7.96 + return _shorts[high_packed_offset]; 7.97 +#ifndef PRODUCT 7.98 + case FIELDINFO_TAG_OFFSET: 7.99 + ShouldNotReachHere2("Asking the contended group for the field with offset"); 7.100 + case FIELDINFO_TAG_BLANK: 7.101 + ShouldNotReachHere2("Asking the contended group for the blank field"); 7.102 +#endif 7.103 + } 7.104 + ShouldNotReachHere(); 7.105 + return 0; 7.106 + } 7.107 + 7.108 + u2 allocation_type() const { 7.109 + u2 lo = _shorts[low_packed_offset]; 7.110 + switch(lo & FIELDINFO_TAG_MASK) { 7.111 + case FIELDINFO_TAG_TYPE_PLAIN: 7.112 + case FIELDINFO_TAG_TYPE_CONTENDED: 7.113 + return (lo >> FIELDINFO_TAG_SIZE); 7.114 +#ifndef PRODUCT 7.115 + case FIELDINFO_TAG_OFFSET: 7.116 + ShouldNotReachHere2("Asking the field type for field with offset"); 7.117 + case FIELDINFO_TAG_BLANK: 7.118 + ShouldNotReachHere2("Asking the field type for the blank field"); 7.119 +#endif 7.120 + } 7.121 + ShouldNotReachHere(); 7.122 + return 0; 7.123 + } 7.124 + 7.125 + bool is_offset_set() const { 7.126 + return (_shorts[low_packed_offset] & FIELDINFO_TAG_MASK) == FIELDINFO_TAG_OFFSET; 7.127 + } 7.128 7.129 Symbol* name(constantPoolHandle cp) const { 7.130 int index = name_index(); 7.131 @@ -106,8 +194,46 @@ 7.132 7.133 void set_access_flags(u2 val) { _shorts[access_flags_offset] = val; } 7.134 void set_offset(u4 val) { 7.135 - _shorts[low_offset] = extract_low_short_from_int(val); 7.136 - _shorts[high_offset] = extract_high_short_from_int(val); 7.137 + val = val << FIELDINFO_TAG_SIZE; // make room for tag 7.138 + _shorts[low_packed_offset] = extract_low_short_from_int(val) | FIELDINFO_TAG_OFFSET; 7.139 + _shorts[high_packed_offset] = extract_high_short_from_int(val); 7.140 + } 7.141 + 7.142 + void set_allocation_type(int type) { 7.143 + u2 lo = _shorts[low_packed_offset]; 7.144 + switch(lo & FIELDINFO_TAG_MASK) { 7.145 + case FIELDINFO_TAG_BLANK: 7.146 + _shorts[low_packed_offset] = ((type << FIELDINFO_TAG_SIZE)) & 0xFFFF; 7.147 + _shorts[low_packed_offset] &= ~FIELDINFO_TAG_MASK; 7.148 + _shorts[low_packed_offset] |= FIELDINFO_TAG_TYPE_PLAIN; 7.149 + return; 7.150 +#ifndef PRODUCT 7.151 + case FIELDINFO_TAG_TYPE_PLAIN: 7.152 + case FIELDINFO_TAG_TYPE_CONTENDED: 7.153 + case FIELDINFO_TAG_OFFSET: 7.154 + ShouldNotReachHere2("Setting the field type with overwriting"); 7.155 +#endif 7.156 + } 7.157 + ShouldNotReachHere(); 7.158 + } 7.159 + 7.160 + void set_contended_group(u2 val) { 7.161 + u2 lo = _shorts[low_packed_offset]; 7.162 + switch(lo & FIELDINFO_TAG_MASK) { 7.163 + case FIELDINFO_TAG_TYPE_PLAIN: 7.164 + _shorts[low_packed_offset] |= FIELDINFO_TAG_TYPE_CONTENDED; 7.165 + _shorts[high_packed_offset] = val; 7.166 + return; 7.167 +#ifndef PRODUCT 7.168 + case FIELDINFO_TAG_TYPE_CONTENDED: 7.169 + ShouldNotReachHere2("Overwriting contended group"); 7.170 + case FIELDINFO_TAG_BLANK: 7.171 + ShouldNotReachHere2("Setting contended group for the blank field"); 7.172 + case FIELDINFO_TAG_OFFSET: 7.173 + ShouldNotReachHere2("Setting contended group for field with offset"); 7.174 +#endif 7.175 + } 7.176 + ShouldNotReachHere(); 7.177 } 7.178 7.179 bool is_internal() const {
8.1 --- a/src/share/vm/oops/fieldStreams.hpp Fri Jan 11 09:53:24 2013 -0800 8.2 +++ b/src/share/vm/oops/fieldStreams.hpp Mon Jan 14 15:17:47 2013 +0100 8.3 @@ -160,9 +160,26 @@ 8.4 return field()->offset(); 8.5 } 8.6 8.7 + int allocation_type() const { 8.8 + return field()->allocation_type(); 8.9 + } 8.10 + 8.11 void set_offset(int offset) { 8.12 field()->set_offset(offset); 8.13 } 8.14 + 8.15 + bool is_offset_set() const { 8.16 + return field()->is_offset_set(); 8.17 + } 8.18 + 8.19 + bool is_contended() const { 8.20 + return field()->is_contended(); 8.21 + } 8.22 + 8.23 + int contended_group() const { 8.24 + return field()->contended_group(); 8.25 + } 8.26 + 8.27 }; 8.28 8.29 // Iterate over only the internal fields
9.1 --- a/src/share/vm/oops/instanceKlass.hpp Fri Jan 11 09:53:24 2013 -0800 9.2 +++ b/src/share/vm/oops/instanceKlass.hpp Mon Jan 14 15:17:47 2013 +0100 9.3 @@ -230,7 +230,8 @@ 9.4 _misc_rewritten = 1 << 0, // methods rewritten. 9.5 _misc_has_nonstatic_fields = 1 << 1, // for sizing with UseCompressedOops 9.6 _misc_should_verify_class = 1 << 2, // allow caching of preverification 9.7 - _misc_is_anonymous = 1 << 3 // has embedded _inner_classes field 9.8 + _misc_is_anonymous = 1 << 3, // has embedded _inner_classes field 9.9 + _misc_is_contended = 1 << 4 // marked with contended annotation 9.10 }; 9.11 u2 _misc_flags; 9.12 u2 _minor_version; // minor version number of class file 9.13 @@ -550,6 +551,17 @@ 9.14 return is_anonymous() ? java_mirror() : class_loader(); 9.15 } 9.16 9.17 + bool is_contended() const { 9.18 + return (_misc_flags & _misc_is_contended) != 0; 9.19 + } 9.20 + void set_is_contended(bool value) { 9.21 + if (value) { 9.22 + _misc_flags |= _misc_is_contended; 9.23 + } else { 9.24 + _misc_flags &= ~_misc_is_contended; 9.25 + } 9.26 + } 9.27 + 9.28 // signers 9.29 objArrayOop signers() const { return _signers; } 9.30 void set_signers(objArrayOop s) { klass_oop_store((oop*)&_signers, s); }
10.1 --- a/src/share/vm/runtime/globals.hpp Fri Jan 11 09:53:24 2013 -0800 10.2 +++ b/src/share/vm/runtime/globals.hpp Mon Jan 14 15:17:47 2013 +0100 10.3 @@ -1075,7 +1075,7 @@ 10.4 \ 10.5 product(intx, ClearFPUAtPark, 0, "(Unsafe,Unstable)" ) \ 10.6 \ 10.7 - product(intx, hashCode, 0, \ 10.8 + product(intx, hashCode, 5, \ 10.9 "(Unstable) select hashCode generation algorithm" ) \ 10.10 \ 10.11 product(intx, WorkAroundNPTLTimedWaitHang, 1, \ 10.12 @@ -1173,6 +1173,18 @@ 10.13 notproduct(bool, PrintCompactFieldsSavings, false, \ 10.14 "Print how many words were saved with CompactFields") \ 10.15 \ 10.16 + notproduct(bool, PrintFieldLayout, false, \ 10.17 + "Print field layout for each class") \ 10.18 + \ 10.19 + product(intx, ContendedPaddingWidth, 128, \ 10.20 + "How many bytes to pad the fields/classes marked @Contended with")\ 10.21 + \ 10.22 + product(bool, EnableContended, true, \ 10.23 + "Enable @Contended annotation support") \ 10.24 + \ 10.25 + product(bool, RestrictContended, true, \ 10.26 + "Restrict @Contended to trusted classes") \ 10.27 + \ 10.28 product(bool, UseBiasedLocking, true, \ 10.29 "Enable biased locking in JVM") \ 10.30 \
11.1 --- a/src/share/vm/runtime/vmStructs.cpp Fri Jan 11 09:53:24 2013 -0800 11.2 +++ b/src/share/vm/runtime/vmStructs.cpp Mon Jan 14 15:17:47 2013 +0100 11.3 @@ -2284,10 +2284,17 @@ 11.4 declare_constant(FieldInfo::name_index_offset) \ 11.5 declare_constant(FieldInfo::signature_index_offset) \ 11.6 declare_constant(FieldInfo::initval_index_offset) \ 11.7 - declare_constant(FieldInfo::low_offset) \ 11.8 - declare_constant(FieldInfo::high_offset) \ 11.9 + declare_constant(FieldInfo::low_packed_offset) \ 11.10 + declare_constant(FieldInfo::high_packed_offset) \ 11.11 declare_constant(FieldInfo::field_slots) \ 11.12 \ 11.13 + /*************************************/ \ 11.14 + /* FieldInfo tag constants */ \ 11.15 + /*************************************/ \ 11.16 + \ 11.17 + declare_preprocessor_constant("FIELDINFO_TAG_SIZE", FIELDINFO_TAG_SIZE) \ 11.18 + declare_preprocessor_constant("FIELDINFO_TAG_OFFSET", FIELDINFO_TAG_OFFSET) \ 11.19 + \ 11.20 /************************************************/ \ 11.21 /* InstanceKlass InnerClassAttributeOffset enum */ \ 11.22 /************************************************/ \