changeset 57838:d9f77baa9880 records-and-sealed

Summary: Add support for Record attributes with annotations Reviewed-by: vromero
author hseigel
date Wed, 25 Sep 2019 15:55:42 +0000
parents fcff15c119f1
children ef06a5eb98d2 eea3e1e0b99d dbb5d90508b2
files src/hotspot/share/classfile/classFileParser.cpp src/hotspot/share/oops/recordComponent.cpp src/hotspot/share/oops/recordComponent.hpp src/hotspot/share/prims/jvmtiClassFileReconstituter.cpp
diffstat 4 files changed, 137 insertions(+), 29 deletions(-) [+]
line wrap: on
line diff
--- a/src/hotspot/share/classfile/classFileParser.cpp	Fri Sep 20 15:54:38 2019 -0400
+++ b/src/hotspot/share/classfile/classFileParser.cpp	Wed Sep 25 15:55:42 2019 +0000
@@ -3292,7 +3292,17 @@
 
     const u2 attributes_count = cfs->get_u2_fast();
     calculate_attr_size += 6;
-    u2 generic_signature_index = 0;
+    u2 generic_sig_index = 0;
+    const u1* runtime_visible_annotations = NULL;
+    int runtime_visible_annotations_length = 0;
+    const u1* runtime_invisible_annotations = NULL;
+    int runtime_invisible_annotations_length = 0;
+    bool runtime_invisible_annotations_exists = false;
+    const u1* runtime_visible_type_annotations = NULL;
+    int runtime_visible_type_annotations_length = 0;
+    const u1* runtime_invisible_type_annotations = NULL;
+    int runtime_invisible_type_annotations_length = 0;
+    bool runtime_invisible_type_annotations_exists = false;
 
     for (int y = 0; y < attributes_count; y++) {
       cfs->guarantee_more(6, CHECK_0);  // attribute_name_index, attribute_length
@@ -3306,33 +3316,92 @@
 
       const Symbol* const attribute_name = cp->symbol_at(attribute_name_index);
       if (attribute_name == vmSymbols::tag_signature()) {
-        if (generic_signature_index != 0) {
+        if (generic_sig_index != 0) {
           classfile_parse_error(
             "Multiple Signature attributes for Record component in class file %s",
             CHECK_0);
         }
         if (attribute_length != 2) {
           classfile_parse_error(
-            "Invalid Signature attribute length %u in class file %s",
+            "Invalid Signature attribute length %u in Record component in class file %s",
             attribute_length, CHECK_0);
         }
-        generic_signature_index = parse_generic_signature_attribute(cfs, CHECK_0);
-        calculate_attr_size += 2;
+        generic_sig_index = parse_generic_signature_attribute(cfs, CHECK_0);
+
+      } else if (attribute_name == vmSymbols::tag_runtime_visible_annotations()) {
+        if (runtime_visible_annotations != NULL) {
+          classfile_parse_error(
+            "Multiple RuntimeVisibleAnnotations attributes for Record component in class file %s", CHECK_0);
+        }
+        runtime_visible_annotations_length = attribute_length;
+        runtime_visible_annotations = cfs->current();
+
+        assert(runtime_visible_annotations != NULL, "null record component visible annotation");
+        cfs->guarantee_more(runtime_visible_annotations_length, CHECK_0);
+        cfs->skip_u1_fast(runtime_visible_annotations_length);
+
+      } else if (attribute_name == vmSymbols::tag_runtime_invisible_annotations()) {
+        if (runtime_invisible_annotations_exists) {
+          classfile_parse_error(
+            "Multiple RuntimeInvisibleAnnotations attributes for Record component in class file %s", CHECK_0);
+        }
+        runtime_invisible_annotations_exists = true;
+        if (PreserveAllAnnotations) {
+          runtime_invisible_annotations_length = attribute_length;
+          runtime_invisible_annotations = cfs->current();
+          assert(runtime_invisible_annotations != NULL, "null record component invisible annotation");
+        }
+        cfs->skip_u1(attribute_length, CHECK_0);
+
+      } else if (attribute_name == vmSymbols::tag_runtime_visible_type_annotations()) {
+        if (runtime_visible_type_annotations != NULL) {
+          classfile_parse_error(
+            "Multiple RuntimeVisibleTypeAnnotations attributes for Record component in class file %s", CHECK_0);
+        }
+        runtime_visible_type_annotations_length = attribute_length;
+        runtime_visible_type_annotations = cfs->current();
+
+        assert(runtime_visible_type_annotations != NULL, "null record component visible type annotation");
+        cfs->guarantee_more(runtime_visible_type_annotations_length, CHECK_0);
+        cfs->skip_u1_fast(runtime_visible_type_annotations_length);
+
+      } else if (attribute_name == vmSymbols::tag_runtime_invisible_type_annotations()) {
+        if (runtime_invisible_type_annotations_exists) {
+          classfile_parse_error(
+            "Multiple RuntimeInvisibleTypeAnnotations attributes for Record component in class file %s", CHECK_0);
+        }
+        runtime_invisible_type_annotations_exists = true;
+        if (PreserveAllAnnotations) {
+          runtime_invisible_type_annotations_length = attribute_length;
+          runtime_invisible_type_annotations = cfs->current();
+          assert(runtime_invisible_type_annotations != NULL, "null record component invisible type annotation");
+        }
+        cfs->skip_u1(attribute_length, CHECK_0);
+
       } else {
         // Skip unknown attributes
         cfs->skip_u1(attribute_length, CHECK_0);
-        calculate_attr_size += attribute_length;
       }
-    }
+      calculate_attr_size += attribute_length;
+    } // End of attributes For loop
+
+    AnnotationArray* annotations = assemble_annotations(runtime_visible_annotations,
+                                                        runtime_visible_annotations_length,
+                                                        runtime_invisible_annotations,
+                                                        runtime_invisible_annotations_length,
+                                                        CHECK_0);
+    AnnotationArray* type_annotations = assemble_annotations(runtime_visible_type_annotations,
+                                                             runtime_visible_type_annotations_length,
+                                                             runtime_invisible_type_annotations,
+                                                             runtime_invisible_type_annotations_length,
+                                                             CHECK_0);
 
     RecordComponent* record_component =
       RecordComponent::allocate(_loader_data, name_index, descriptor_index,
-                                attributes_count, generic_signature_index,
-                                NULL /* TBD annotations */, CHECK_0);
+                                attributes_count, generic_sig_index,
+                                annotations, type_annotations, CHECK_0);
     record_components->at_put(x, record_component);
-
-    // TBD need to process possible annotation attributes
-  }
+  }  // End of component processing loop
 
   // Restore buffer's current position.
   cfs->set_current(current_mark);
--- a/src/hotspot/share/oops/recordComponent.cpp	Fri Sep 20 15:54:38 2019 -0400
+++ b/src/hotspot/share/oops/recordComponent.cpp	Wed Sep 25 15:55:42 2019 +0000
@@ -24,10 +24,11 @@
 
 #include "precompiled.hpp"
 #include "logging/log.hpp"
+#include "memory/metadataFactory.hpp"
+#include "memory/metaspace.hpp"
+#include "memory/metaspaceClosure.hpp"
 #include "oops/annotations.hpp"
 #include "oops/instanceKlass.hpp"
-#include "memory/metaspace.hpp"
-#include "memory/metaspaceClosure.hpp"
 #include "oops/recordComponent.hpp"
 #include "utilities/globalDefinitions.hpp"
 
@@ -35,21 +36,26 @@
                                            u2 name_index, u2 descriptor_index,
                                            u2 attributes_count,
                                            u2 generic_signature_index,
-                                           Annotations* annotations, TRAPS) {
+                                           AnnotationArray* annotations,
+                                           AnnotationArray* type_annotations, TRAPS) {
   return new (loader_data, size(), MetaspaceObj::RecordComponentType, THREAD)
          RecordComponent(name_index, descriptor_index, attributes_count,
-                         generic_signature_index, annotations);
+                         generic_signature_index, annotations, type_annotations);
 }
 
 void RecordComponent::deallocate_contents(ClassLoaderData* loader_data) {
   if (annotations() != NULL) {
-    annotations()->deallocate_contents(loader_data);
+    MetadataFactory::free_array<u1>(loader_data, annotations());
+  }
+  if (type_annotations() != NULL) {
+    MetadataFactory::free_array<u1>(loader_data, type_annotations());
   }
 }
 
 void RecordComponent::metaspace_pointers_do(MetaspaceClosure* it) {
   log_trace(cds)("Iter(RecordComponent): %p", this);
   it->push(&_annotations);
+  it->push(&_type_annotations);
 }
 
 void RecordComponent::print_value_on(outputStream* st) const {
@@ -67,7 +73,11 @@
   st->cr();
   if (_annotations != NULL) {
     st->print_cr("record component annotations");
-    _annotations->print_on(st);
+    _annotations->print_value_on(st);
+  }
+  if (_type_annotations != NULL) {
+    st->print_cr("record component type annotations");
+    _type_annotations->print_value_on(st);
   }
 }
 #endif // PRODUCT
--- a/src/hotspot/share/oops/recordComponent.hpp	Fri Sep 20 15:54:38 2019 -0400
+++ b/src/hotspot/share/oops/recordComponent.hpp	Wed Sep 25 15:55:42 2019 +0000
@@ -25,6 +25,7 @@
 #ifndef SHARE_OOPS_RECORDCOMPONENT_HPP
 #define SHARE_OOPS_RECORDCOMPONENT_HPP
 
+#include "memory/heapInspection.hpp"
 #include "oops/annotations.hpp"
 #include "oops/metadata.hpp"
 #include "utilities/globalDefinitions.hpp"
@@ -32,7 +33,8 @@
 // This class stores information extracted from the Record class attribute.
 class RecordComponent: public MetaspaceObj {
   private:
-    Annotations* _annotations;
+    AnnotationArray* _annotations;
+    AnnotationArray* _type_annotations;
     u2 _name_index;
     u2 _descriptor_index;
     u2 _attributes_count;
@@ -43,9 +45,10 @@
 
   public:
     RecordComponent(u2 name_index, u2 descriptor_index, u2 attributes_count,
-                    u2 generic_signature_index, Annotations* annotations):
-                    _annotations(annotations), _name_index(name_index),
-                    _descriptor_index(descriptor_index),
+                    u2 generic_signature_index, AnnotationArray* annotations,
+                    AnnotationArray* type_annotations):
+                    _annotations(annotations), _type_annotations(type_annotations),
+                    _name_index(name_index), _descriptor_index(descriptor_index),
                     _attributes_count(attributes_count),
                     _generic_signature_index(generic_signature_index) { }
 
@@ -54,7 +57,8 @@
                                      u2 name_index, u2 descriptor_index,
                                      u2 attributes_count,
                                      u2 generic_signature_index,
-                                     Annotations* annotations, TRAPS);
+                                     AnnotationArray* annotations,
+                                     AnnotationArray* type_annotations, TRAPS);
 
     void deallocate_contents(ClassLoaderData* loader_data);
 
@@ -66,7 +70,8 @@
 
     u2 generic_signature_index() const { return _generic_signature_index; }
 
-    Annotations* annotations() const { return _annotations; }
+    AnnotationArray* annotations() const { return _annotations; }
+    AnnotationArray* type_annotations() const { return _type_annotations; }
 
     // Size of RecordComponent, not including size of any annotations.
     static int size() { return sizeof(RecordComponent) / wordSize; }
@@ -80,7 +85,15 @@
 
 #if INCLUDE_SERVICES
     void collect_statistics(KlassSizeStats *sz) const {
-      if (_annotations != NULL) _annotations->collect_statistics(sz);
+      // TBD is this right?
+      if (_annotations != NULL) {
+        sz->_annotations_bytes += sz->count(_annotations);
+        sz->_ro_bytes += sz->count(_annotations);
+      }
+      if (_type_annotations != NULL) {
+        sz->_annotations_bytes += sz->count(_type_annotations);
+        sz->_ro_bytes += sz->count(_type_annotations);
+      }
     }
 #endif
 
--- a/src/hotspot/share/prims/jvmtiClassFileReconstituter.cpp	Fri Sep 20 15:54:38 2019 -0400
+++ b/src/hotspot/share/prims/jvmtiClassFileReconstituter.cpp	Wed Sep 25 15:55:42 2019 +0000
@@ -447,8 +447,14 @@
 //  Record {
 //    u2 attribute_name_index;
 //    u4 attribute_length;
-//    u2 number_of_classes;
-//    u2 classes[number_of_classes];
+//    u2 components_count;
+//    component_info components[components_count];
+//  }
+//  component_info {
+//    u2 name_index;
+//    u2 descriptor_index
+//    u2 attributs_count;
+//    attribute_info_attributes[attributes_count];
 //  }
 void JvmtiClassFileReconstituter::write_record_attribute() {
   Array<RecordComponent*>* components = ik()->record_components();
@@ -462,7 +468,12 @@
       length += 8; // Signature attribute size
       assert(component->attributes_count() > 0, "Bad component attributes count");
     }
-    // TBD check for annotation attributes and add their size.
+    if (component->annotations() != NULL) {
+      length += 6 + component->annotations()->length();
+    }
+    if (component->type_annotations() != NULL) {
+      length += 6 + component->type_annotations()->length();
+    }
   }
 
   write_attribute_name_index("Record");
@@ -476,7 +487,12 @@
     if (component->generic_signature_index() != 0) {
       write_signature_attribute(component->generic_signature_index());
     }
-    // TBD need to write annotation stuff here!
+    if (component->annotations() != NULL) {
+      write_annotations_attribute("RuntimeVisibleAnnotations", component->annotations());
+    }
+    if (component->type_annotations() != NULL) {
+      write_annotations_attribute("RuntimeVisibleTypeAnnotations", component->type_annotations());
+    }
   }
 }