8003985: Support @Contended Annotation - JEP 142

Mon, 14 Jan 2013 15:17:47 +0100

author
jwilhelm
date
Mon, 14 Jan 2013 15:17:47 +0100
changeset 4430
4a916f2ce331
parent 4429
90a92d5bca17
child 4432
5b6a231e5a86
child 4473
edd23b35b1a5

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>

agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java file | annotate | diff | comparison | revisions
src/cpu/sparc/vm/vm_version_sparc.cpp file | annotate | diff | comparison | revisions
src/cpu/x86/vm/vm_version_x86.cpp file | annotate | diff | comparison | revisions
src/share/vm/classfile/classFileParser.cpp file | annotate | diff | comparison | revisions
src/share/vm/classfile/classFileParser.hpp file | annotate | diff | comparison | revisions
src/share/vm/classfile/vmSymbols.hpp file | annotate | diff | comparison | revisions
src/share/vm/oops/fieldInfo.hpp file | annotate | diff | comparison | revisions
src/share/vm/oops/fieldStreams.hpp file | annotate | diff | comparison | revisions
src/share/vm/oops/instanceKlass.hpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/globals.hpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/vmStructs.cpp file | annotate | diff | comparison | revisions
     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    /************************************************/                      \

mercurial