< prev index next >

src/hotspot/share/memory/heapInspection.cpp

Print this page
*** 33,12 ***
--- 33,15 ---
  #include "memory/heapInspection.hpp"
  #include "memory/resourceArea.hpp"
  #include "memory/universe.hpp"
  #include "oops/oop.inline.hpp"
  #include "oops/reflectionAccessorImplKlassHelper.hpp"
+ #include "oops/inlineKlass.inline.hpp"
+ #include "runtime/reflectionUtils.hpp"
  #include "runtime/atomic.hpp"
  #include "runtime/os.hpp"
+ #include "runtime/fieldDescriptor.inline.hpp"
  #include "services/memTracker.hpp"
  #include "utilities/globalDefinitions.hpp"
  #include "utilities/macros.hpp"
  #include "utilities/stack.inline.hpp"
  

*** 514,10 ***
--- 517,142 ---
    void do_cinfo(KlassInfoEntry* cie) {
      _cih->add(cie);
    }
  };
  
+ 
+ class FindClassByNameClosure : public KlassInfoClosure {
+  private:
+   GrowableArray<Klass*>* _klasses;
+   Symbol* _classname;
+  public:
+   FindClassByNameClosure(GrowableArray<Klass*>* klasses, Symbol* classname) :
+     _klasses(klasses), _classname(classname) { }
+ 
+   void do_cinfo(KlassInfoEntry* cie) {
+     if (cie->klass()->name() == _classname) {
+       _klasses->append(cie->klass());
+     }
+   }
+ };
+ 
+ class FieldDesc {
+ private:
+   Symbol* _name;
+   Symbol* _signature;
+   int _offset;
+   int _index;
+   InstanceKlass* _holder;
+   AccessFlags _access_flags;
+  public:
+   FieldDesc() {
+     _name = NULL;
+     _signature = NULL;
+     _offset = -1;
+     _index = -1;
+     _holder = NULL;
+     _access_flags = AccessFlags();
+   }
+   FieldDesc(fieldDescriptor& fd) {
+     _name = fd.name();
+     _signature = fd.signature();
+     _offset = fd.offset();
+     _index = fd.index();
+     _holder = fd.field_holder();
+     _access_flags = fd.access_flags();
+   }
+   const Symbol* name() { return _name;}
+   const Symbol* signature() { return _signature; }
+   const int offset() { return _offset; }
+   const int index() { return _index; }
+   const InstanceKlass* holder() { return _holder; }
+   const AccessFlags& access_flags() { return _access_flags; }
+   const bool is_inline_type() { return Signature::basic_type(_signature) == T_INLINE_TYPE; }
+ };
+ 
+ static int compare_offset(FieldDesc* f1, FieldDesc* f2) {
+    return f1->offset() > f2->offset() ? 1 : -1;
+ }
+ 
+ static void print_field(outputStream* st, int level, int offset, FieldDesc& fd, bool is_inline_type, bool is_inlined ) {
+   const char* inlined_msg = "";
+   if (is_inline_type) {
+     inlined_msg = is_inlined ? "inlined" : "not inlined";
+   }
+   st->print_cr("  @ %d %*s \"%s\" %s %s %s",
+       offset, level * 3, "",
+       fd.name()->as_C_string(),
+       fd.signature()->as_C_string(),
+       is_inline_type ? " // inline type " : "",
+       inlined_msg);
+ }
+ 
+ static void print_inlined_field(outputStream* st, int level, int offset, InstanceKlass* klass) {
+   assert(klass->is_inline_klass(), "Only inline types can be inlined");
+   InlineKlass* vklass = InlineKlass::cast(klass);
+   GrowableArray<FieldDesc>* fields = new (ResourceObj::C_HEAP, mtServiceability) GrowableArray<FieldDesc>(100, mtServiceability);
+   for (FieldStream fd(klass, false, false); !fd.eos(); fd.next()) {
+     if (!fd.access_flags().is_static()) {
+       fields->append(FieldDesc(fd.field_descriptor()));
+     }
+   }
+   fields->sort(compare_offset);
+   for(int i = 0; i < fields->length(); i++) {
+     FieldDesc fd = fields->at(i);
+     int offset2 = offset + fd.offset() - vklass->first_field_offset();
+     print_field(st, level, offset2, fd,
+         fd.is_inline_type(), fd.holder()->field_is_inlined(fd.index()));
+     if (fd.holder()->field_is_inlined(fd.index())) {
+       print_inlined_field(st, level + 1, offset2 ,
+           InstanceKlass::cast(fd.holder()->get_inline_type_field_klass(fd.index())));
+     }
+   }
+ }
+ 
+ void PrintClassLayout::print_class_layout(outputStream* st, char* class_name) {
+   KlassInfoTable cit(true);
+   if (cit.allocation_failed()) {
+     st->print_cr("ERROR: Ran out of C-heap; hierarchy not generated");
+     return;
+   }
+ 
+   Thread* THREAD = Thread::current();
+ 
+   Symbol* classname = SymbolTable::probe(class_name, (int)strlen(class_name));
+ 
+   GrowableArray<Klass*>* klasses = new (ResourceObj::C_HEAP, mtServiceability) GrowableArray<Klass*>(100, mtServiceability);
+ 
+   FindClassByNameClosure fbnc(klasses, classname);
+   cit.iterate(&fbnc);
+ 
+   for(int i = 0; i < klasses->length(); i++) {
+     Klass* klass = klasses->at(i);
+     if (!klass->is_instance_klass()) continue;  // Skip
+     InstanceKlass* ik = InstanceKlass::cast(klass);
+     int tab = 1;
+     st->print_cr("Class %s [@%s]:", klass->name()->as_C_string(),
+         klass->class_loader_data()->loader_name());
+     ResourceMark rm;
+     GrowableArray<FieldDesc>* fields = new (ResourceObj::C_HEAP, mtServiceability) GrowableArray<FieldDesc>(100, mtServiceability);
+     for (FieldStream fd(ik, false, false); !fd.eos(); fd.next()) {
+       if (!fd.access_flags().is_static()) {
+         fields->append(FieldDesc(fd.field_descriptor()));
+       }
+     }
+     fields->sort(compare_offset);
+     for(int i = 0; i < fields->length(); i++) {
+       FieldDesc fd = fields->at(i);
+       print_field(st, 0, fd.offset(), fd, fd.is_inline_type(), fd.holder()->field_is_inlined(fd.index()));
+       if (fd.holder()->field_is_inlined(fd.index())) {
+         print_inlined_field(st, 1, fd.offset(),
+             InstanceKlass::cast(fd.holder()->get_inline_type_field_klass(fd.index())));
+       }
+     }
+   }
+   st->cr();
+ }
+ 
  class RecordInstanceClosure : public ObjectClosure {
   private:
    KlassInfoTable* _cit;
    uintx _missed_count;
    BoolObjectClosure* _filter;
< prev index next >