< prev index next >

src/hotspot/share/oops/fieldStreams.hpp

Print this page
@@ -37,10 +37,11 @@
  // iterates over fields that have been injected by the JVM.
  // AllFieldStream exposes all fields and should only be used in rare
  // cases.
  // HierarchicalFieldStream allows to also iterate over fields of supertypes.
  class FieldStreamBase : public StackObj {
+ 
   protected:
    const Array<u1>*    _fieldinfo_stream;
    FieldInfoReader     _reader;
    constantPoolHandle  _constants;
    int                 _index;

@@ -108,18 +109,30 @@
  
    int offset() const {
      return field()->offset();
    }
  
+   bool is_null_free_inline_type() {
+     return field()->field_flags().is_null_free_inline_type();
+   }
+ 
+   bool is_flat() const {
+     return field()->field_flags().is_flat();
+   }
+ 
    bool is_contended() const {
      return field()->is_contended();
    }
  
    int contended_group() const {
      return field()->contended_group();
    }
  
+   int null_marker_offset() const {
+     return field()->null_marker_offset();
+   }
+ 
    // Convenient methods
  
    const FieldInfo& to_FieldInfo() const {
      return _fi_buf;
    }

@@ -178,13 +191,91 @@
   public:
    AllFieldStream(Array<u1>* fieldinfo, ConstantPool* constants): FieldStreamBase(fieldinfo, constants) {}
    AllFieldStream(const InstanceKlass* k):      FieldStreamBase(k->fieldinfo_stream(), k->constants()) {}
  };
  
- // Iterate over fields including the ones declared in supertypes
+ /* Very generally, a base class for a stream adapter, a derived class just implements
+  * current_stream that returns a FieldStreamType, and this adapter takes care of providing
+  * the methods of FieldStreamBase.
+  *
+  * In practice, this is used to provide a stream over the fields of a class and its superclasses
+  * and interfaces. The derived class of HierarchicalFieldStreamBase decides in which order we iterate
+  * on the superclasses (and interfaces), and the template parameter FieldStreamType is the underlying
+  * stream we use to iterate over the fields each class. Methods such as done and next are still up to
+  * the derived classes, allowing them to iterate over the class hierarchy, but also skip elements that
+  * the underlying FieldStreamType would otherwise include.
+  */
+ template<typename FieldStreamType>
+ class HierarchicalFieldStreamBase : public StackObj {
+   virtual FieldStreamType& current_stream() = 0;
+   virtual const FieldStreamType& current_stream() const = 0;
+ 
+ public:
+   // bridge functions from FieldStreamBase
+   int index() const {
+     return current_stream().index();
+   }
+ 
+   AccessFlags access_flags() const {
+     return current_stream().access_flags();
+   }
+ 
+   FieldInfo::FieldFlags field_flags() const {
+     return current_stream().field_flags();
+   }
+ 
+   Symbol* name() const {
+     return current_stream().name();
+   }
+ 
+   Symbol* signature() const {
+     return current_stream().signature();
+   }
+ 
+   Symbol* generic_signature() const {
+     return current_stream().generic_signature();
+   }
+ 
+   int offset() const {
+     return current_stream().offset();
+   }
+ 
+   bool is_contended() const {
+     return current_stream().is_contended();
+   }
+ 
+   int contended_group() const {
+     return current_stream().contended_group();
+   }
+ 
+   FieldInfo to_FieldInfo() {
+     return current_stream().to_FieldInfo();
+   }
+ 
+   fieldDescriptor& field_descriptor() const {
+     return current_stream().field_descriptor();
+   }
+ 
+   bool is_flat() const {
+     return current_stream().is_flat();
+   }
+ 
+   bool is_null_free_inline_type() {
+     return current_stream().is_null_free_inline_type();
+   }
+ 
+   int null_marker_offset() {
+     return current_stream().null_marker_offset();
+   }
+ };
+ 
+ /* Iterate over fields including the ones declared in supertypes.
+  * Derived classes are traversed before base classes, and interfaces
+  * at the end.
+  */
  template<typename FieldStreamType>
- class HierarchicalFieldStream : public StackObj  {
+ class HierarchicalFieldStream final : public HierarchicalFieldStreamBase<FieldStreamType>  {
   private:
    const Array<InstanceKlass*>* _interfaces;
    InstanceKlass* _next_klass; // null indicates no more type to visit
    FieldStreamType _current_stream;
    int _interface_index;

@@ -218,12 +309,15 @@
        assert(!_current_stream.done(), "created empty stream");
        _next_klass = next_klass_with_fields();
      }
    }
  
+   FieldStreamType& current_stream() override { return _current_stream; }
+   const FieldStreamType& current_stream() const override { return _current_stream; }
+ 
   public:
-   HierarchicalFieldStream(InstanceKlass* klass) :
+   explicit HierarchicalFieldStream(InstanceKlass* klass) :
      _interfaces(klass->transitive_interfaces()),
      _next_klass(klass),
      _current_stream(FieldStreamType(klass)),
      _interface_index(_interfaces->length()) {
        prepare();

@@ -233,51 +327,69 @@
      _current_stream.next();
      next_stream_if_done();
    }
  
    bool done() const { return _next_klass == nullptr && _current_stream.done(); }
+ };
  
-   // bridge functions from FieldStreamBase
- 
-   AccessFlags access_flags() const {
-     return _current_stream.access_flags();
-   }
- 
-   FieldInfo::FieldFlags field_flags() const {
-     return _current_stream.field_flags();
-   }
- 
-   Symbol* name() const {
-     return _current_stream.name();
-   }
- 
-   Symbol* signature() const {
-     return _current_stream.signature();
+ /* Iterates on the fields of a class and its super-class top-down (java.lang.Object first)
+  * Doesn't traverse interfaces for now, because it's not clear which order would make sense
+  * Let's decide when or if the need arises. Since we are not traversing interfaces, we
+  * wouldn't get all the static fields, and since the current use-case of this stream does not
+  * care about static fields, we restrict it to regular non-static fields.
+  */
+ class TopDownHierarchicalNonStaticFieldStreamBase final : public HierarchicalFieldStreamBase<JavaFieldStream> {
+   GrowableArray<InstanceKlass*>* _super_types;  // Self and super type, bottom up
+   int _current_stream_index;
+   JavaFieldStream _current_stream;
+ 
+   void next_stream_if_needed() {
+     precond(_current_stream_index >= 0);
+     while (_current_stream.done()) {
+       _current_stream_index--;
+       if (_current_stream_index < 0) {
+         return;
+       }
+       _current_stream = JavaFieldStream(_super_types->at(_current_stream_index));
+     }
    }
  
-   Symbol* generic_signature() const {
-     return _current_stream.generic_signature();
+   GrowableArray<InstanceKlass*>* get_super_types(InstanceKlass* klass) {
+     auto super_types = new GrowableArray<InstanceKlass*>();
+     do {
+       super_types->push(klass);
+     } while ((klass = klass->java_super()) != nullptr);
+     return super_types;
    }
  
-   int offset() const {
-     return _current_stream.offset();
+   void raw_next() {
+     _current_stream.next();
+     next_stream_if_needed();
    }
  
-   bool is_contended() const {
-     return _current_stream.is_contended();
+   void closest_non_static() {
+     while (!done() && access_flags().is_static()) {
+       raw_next();
+     }
    }
  
-   int contended_group() const {
-     return _current_stream.contended_group();
-   }
+   JavaFieldStream& current_stream() override { return _current_stream; }
+   const JavaFieldStream& current_stream() const override { return _current_stream; }
  
-   FieldInfo to_FieldInfo() {
-     return _current_stream.to_FieldInfo();
+  public:
+   explicit TopDownHierarchicalNonStaticFieldStreamBase(InstanceKlass* klass) :
+     _super_types(get_super_types(klass)),
+     _current_stream_index(_super_types->length() - 1),
+     _current_stream(JavaFieldStream(_super_types->at(_current_stream_index))) {
+     next_stream_if_needed();
+     closest_non_static();
    }
  
-   fieldDescriptor& field_descriptor() const {
-     return _current_stream.field_descriptor();
+   void next() {
+     raw_next();
+     closest_non_static();
    }
  
+   bool done() const { return _current_stream_index < 0; }
  };
  
  #endif // SHARE_OOPS_FIELDSTREAMS_HPP
< prev index next >