< prev index next >

src/hotspot/share/classfile/fieldLayoutBuilder.cpp

Print this page
rev 59083 : DRAFT 8236522: NonTearable marker interface for inline classes to enforce atomicity

@@ -537,11 +537,14 @@
   _first_field_offset(-1),
   _exact_size_in_bytes(-1),
   _has_nonstatic_fields(false),
   _is_contended(is_contended),
   _is_value_type(is_value_type),
-  _has_flattening_information(is_value_type) {}
+  _has_flattening_information(is_value_type),
+  _has_nonatomic_values(false),
+  _atomic_field_count(0)
+ {}
 
 FieldGroup* FieldLayoutBuilder::get_or_create_contended_group(int g) {
   assert(g > 0, "must only be called for named contended groups");
   FieldGroup* fg = NULL;
   for (int i = 0; i < _contended_groups.length(); i++) {

@@ -577,10 +580,11 @@
     FieldGroup* group = NULL;
     if (fs.access_flags().is_static()) {
       group = _static_fields;
     } else {
       _has_nonstatic_fields = true;
+      _atomic_field_count++;  // we might decrement this
       if (fs.is_contended()) {
         int g = fs.contended_group();
         if (g == 0) {
           group = new FieldGroup(true);
           _contended_groups.append(group);

@@ -624,18 +628,27 @@
             SystemDictionary::resolve_flattenable_field_or_fail(&fs,
                                                                 Handle(THREAD, _class_loader_data->class_loader()),
                                                                 _protection_domain, true, THREAD);
         assert(klass != NULL, "Sanity check");
         ValueKlass* vk = ValueKlass::cast(klass);
-        bool has_flattenable_size = (ValueFieldMaxFlatSize < 0)
-                                   || (vk->size_helper() * HeapWordSize) <= ValueFieldMaxFlatSize;
+        bool too_big_to_flatten = (ValueFieldMaxFlatSize >= 0 &&
+                                   (vk->size_helper() * HeapWordSize) > ValueFieldMaxFlatSize);
+        bool too_atomic_to_flatten = vk->is_declared_atomic();
+        bool too_volatile_to_flatten = fs.access_flags().is_volatile();
+        if (vk->is_naturally_atomic()) {
+          too_atomic_to_flatten = false;
+          //too_volatile_to_flatten = false; //FIXME
         // volatile fields are currently never flattened, this could change in the future
-        bool flattened = !fs.access_flags().is_volatile() && has_flattenable_size;
-        if (flattened) {
+        }
+        if (!(too_big_to_flatten | too_atomic_to_flatten | too_volatile_to_flatten)) {
           group->add_flattened_field(fs, vk);
           _nonstatic_oopmap_count += vk->nonstatic_oop_map_count();
           fs.set_flattened(true);
+          if (!vk->is_atomic()) {  // flat and non-atomic: take note
+            _has_nonatomic_values = true;
+            _atomic_field_count--;  // every other field is atomic but this one
+          }
         } else {
           _nonstatic_oopmap_count++;
           group->add_oop_field(fs);
         }
       }

@@ -672,10 +685,11 @@
     int field_alignment = 1;
     if (fs.access_flags().is_static()) {
       group = _static_fields;
     } else {
       _has_nonstatic_fields = true;
+      _atomic_field_count++;  // we might decrement this
       group = _root_group;
     }
     assert(group != NULL, "invariant");
     BasicType type = Signature::basic_type(fs.signature());
     switch(type) {

@@ -714,17 +728,28 @@
             SystemDictionary::resolve_flattenable_field_or_fail(&fs,
                 Handle(THREAD, _class_loader_data->class_loader()),
                 _protection_domain, true, CHECK);
         assert(klass != NULL, "Sanity check");
         ValueKlass* vk = ValueKlass::cast(klass);
-        bool flattened = (ValueFieldMaxFlatSize < 0)
-                         || (vk->size_helper() * HeapWordSize) <= ValueFieldMaxFlatSize;
-        if (flattened) {
+        bool too_big_to_flatten = (ValueFieldMaxFlatSize >= 0 &&
+                                   (vk->size_helper() * HeapWordSize) > ValueFieldMaxFlatSize);
+        bool too_atomic_to_flatten = vk->is_declared_atomic();
+        bool too_volatile_to_flatten = fs.access_flags().is_volatile();
+        if (vk->is_naturally_atomic()) {
+          too_atomic_to_flatten = false;
+          //too_volatile_to_flatten = false; //FIXME
+          // volatile fields are currently never flattened, this could change in the future
+        }
+        if (!(too_big_to_flatten | too_atomic_to_flatten | too_volatile_to_flatten)) {
           group->add_flattened_field(fs, vk);
           _nonstatic_oopmap_count += vk->nonstatic_oop_map_count();
           field_alignment = vk->get_alignment();
           fs.set_flattened(true);
+          if (!vk->is_atomic()) {  // flat and non-atomic: take note
+            _has_nonatomic_values = true;
+            _atomic_field_count--;  // every other field is atomic but this one
+          }
         } else {
           _nonstatic_oopmap_count++;
           field_alignment = type2aelembytes(T_OBJECT);
           group->add_oop_field(fs);
         }

@@ -981,10 +1006,23 @@
   _info->_instance_size = align_object_size(instance_end / wordSize);
   _info->_static_field_size = static_fields_size;
   _info->_nonstatic_field_size = (nonstatic_field_end - instanceOopDesc::base_offset_in_bytes()) / heapOopSize;
   _info->_has_nonstatic_fields = _has_nonstatic_fields;
 
+  // A value type is naturally atomic if it has just one field, and
+  // that field is simple enough.
+  _info->_is_naturally_atomic = (_is_value_type &&
+                                 (_atomic_field_count <= 1) &&
+                                 !_has_nonatomic_values &&
+                                 _contended_groups.is_empty());
+  // This may be too restrictive, since if all the fields fit in 64
+  // bits we could make the decision to align instances of this class
+  // to 64-bit boundaries, and load and store them as single words.
+  // And on machines which supported larger atomics we could similarly
+  // allow larger values to be atomic, if properly aligned.
+
+
   if (PrintFieldLayout) {
     ResourceMark rm;
     tty->print_cr("Layout of class %s", _classname->as_C_string());
     tty->print_cr("Instance fields:");
     _layout->print(tty, false, _super_klass);
< prev index next >