< prev index next >

src/hotspot/share/cds/aotMapLogger.cpp

Print this page
@@ -534,11 +534,11 @@
      os::print_hex_dump(&lsh, base, top, unitsize, /* print_ascii=*/true, /* bytes_per_line=*/32, requested_base);
    }
  }
  
  #if INCLUDE_CDS_JAVA_HEAP
- // FakeOop (and subclasses FakeMirror, FakeString, FakeObjArray, FakeTypeArray) are used to traverse
+ // FakeOop (and subclasses FakeMirror, FakeString, FakeRefArray, FakeFlatArray, FakeTypeArray) are used to traverse
  // and print the (image of) heap objects stored in the AOT cache. These objects are different than regular oops:
  // - They do not reside inside the range of the heap.
  // - For +UseCompressedOops: pointers may use a different narrowOop encoding: see FakeOop::read_oop_at(narrowOop*)
  // - For -UseCompressedOops: pointers are not direct: see FakeOop::read_oop_at(oop*)
  //

@@ -550,33 +550,34 @@
  // fake oops for logging.
  class AOTMapLogger::FakeOop {
    OopDataIterator* _iter;
    OopData _data;
  
-   address* buffered_field_addr(int field_offset) {
-     return (address*)(buffered_addr() + field_offset);
-   }
- 
  public:
    RequestedMetadataAddr metadata_field(int field_offset) {
      return RequestedMetadataAddr(*(address*)(buffered_field_addr(field_offset)));
    }
  
    address buffered_addr() {
      return _data._buffered_addr;
    }
  
+   address* buffered_field_addr(int field_offset) {
+     return (address*)(buffered_addr() + field_offset);
+   }
+ 
    // Return an "oop" pointer so we can use APIs that accept regular oops. This
    // must be used with care, as only a limited number of APIs can work with oops that
    // live outside of the range of the heap.
    oop raw_oop() { return _data._raw_oop; }
  
    FakeOop() : _data() {}
    FakeOop(OopDataIterator* iter, OopData data) : _iter(iter), _data(data) {}
  
    FakeMirror as_mirror();
-   FakeObjArray as_obj_array();
+   FakeRefArray as_ref_array();
+   FakeFlatArray as_flat_array();
    FakeString as_string();
    FakeTypeArray as_type_array();
  
    RequestedMetadataAddr klass() {
      address rk = (address)real_klass();

@@ -628,22 +629,36 @@
  
    FakeOop read_oop_at(oop* addr) { // -UseCompressedOops
      return FakeOop(_iter, _iter->obj_at(addr));
    }
  
+   FakeOop read_inline_oop_at(address value_addr, Klass* k) {
+     OopData data = {
+       value_addr,                                         // _buffered_addr, address of the flat value shifted by the payload offset
+       requested_addr() + (value_addr - buffered_addr()),  // _requested_addr
+       target_location() + (value_addr - buffered_addr()), // _target_location
+       0,                                                  // _narrow_location, narrow oop not used
+       cast_to_oop(value_addr),                            // _raw_oop
+       k,                                                  // _klass
+       0,                                                  // _size
+       false                                               // _is_root_segment
+     };
+     return FakeOop(_iter, data);
+   }
+ 
    FakeOop obj_field(int field_offset) {
      if (UseCompressedOops) {
        return read_oop_at(raw_oop()->field_addr<narrowOop>(field_offset));
      } else {
        return read_oop_at(raw_oop()->field_addr<oop>(field_offset));
      }
    }
  
-   void print_non_oop_field(outputStream* st, fieldDescriptor* fd) {
+   void print_non_oop_field(outputStream* st, fieldDescriptor* fd, int indent = 0, int base_offset = 0) {
      // fd->print_on_for() works for non-oop fields in fake oops
      precond(fd->field_type() != T_ARRAY && fd->field_type() != T_OBJECT);
-     fd->print_on_for(st, raw_oop());
+     fd->print_on_for(st, raw_oop(), indent, base_offset);
    }
  }; // AOTMapLogger::FakeOop
  
  class AOTMapLogger::FakeMirror : public AOTMapLogger::FakeOop {
  public:

@@ -659,29 +674,53 @@
    int static_oop_field_count() {
      return java_lang_Class::static_oop_field_count(raw_oop());
    }
  }; // AOTMapLogger::FakeMirror
  
- class AOTMapLogger::FakeObjArray : public AOTMapLogger::FakeOop {
-   objArrayOop raw_objArrayOop() {
-     return (objArrayOop)raw_oop();
+ class AOTMapLogger::FakeRefArray : public AOTMapLogger::FakeOop {
+   refArrayOop raw_refArrayOop() {
+     return (refArrayOop)raw_oop();
    }
  
  public:
-   FakeObjArray(OopDataIterator* iter, OopData data) : FakeOop(iter, data) {}
+   FakeRefArray(OopDataIterator* iter, OopData data) : FakeOop(iter, data) {}
  
    int length() {
-     return raw_objArrayOop()->length();
+     return raw_refArrayOop()->length();
    }
    FakeOop obj_at(int i) {
      if (UseCompressedOops) {
-       return read_oop_at(raw_objArrayOop()->obj_at_addr<narrowOop>(i));
+       return read_oop_at(raw_refArrayOop()->obj_at_addr<narrowOop>(i));
      } else {
-       return read_oop_at(raw_objArrayOop()->obj_at_addr<oop>(i));
+       return read_oop_at(raw_refArrayOop()->obj_at_addr<oop>(i));
      }
    }
- }; // AOTMapLogger::FakeObjArray
+ }; // AOTMapLogger::FakeRefArray
+ 
+ class AOTMapLogger::FakeFlatArray : public AOTMapLogger::FakeOop {
+   flatArrayOop raw_flatArrayOop() {
+     return (flatArrayOop)raw_oop();
+   }
+ 
+ public:
+   FakeFlatArray(OopDataIterator* iter, OopData data) : FakeOop(iter, data) {}
+ 
+   int length() {
+     return raw_flatArrayOop()->length();
+   }
+ 
+   // Create a wrapper for an archived flat array element
+   FakeOop element_at(int i) {
+     InlineKlass* elem_k = ((FlatArrayKlass*)real_klass())->element_klass();
+     address value_addr = (address)raw_flatArrayOop()->value_at_addr(i, real_klass()->layout_helper()) - elem_k->payload_offset();
+     return read_inline_oop_at(value_addr, elem_k);
+   }
+ 
+   int element_offset_at(int i) {
+     return (address)raw_flatArrayOop()->value_at_addr(i, real_klass()->layout_helper()) - cast_from_oop<address>(raw_flatArrayOop());
+   }
+ }; // AOTMapLogger::FakeFlatArray
  
  class AOTMapLogger::FakeString : public AOTMapLogger::FakeOop {
  public:
    FakeString(OopDataIterator* iter, OopData data) : FakeOop(iter, data) {}
  

@@ -717,13 +756,18 @@
  AOTMapLogger::FakeMirror AOTMapLogger::FakeOop::as_mirror() {
    precond(real_klass() == vmClasses::Class_klass());
    return FakeMirror(_iter, _data);
  }
  
- AOTMapLogger::FakeObjArray AOTMapLogger::FakeOop::as_obj_array() {
-   precond(real_klass()->is_objArray_klass());
-   return FakeObjArray(_iter, _data);
+ AOTMapLogger::FakeRefArray AOTMapLogger::FakeOop::as_ref_array() {
+   precond(real_klass()->is_refArray_klass());
+   return FakeRefArray(_iter, _data);
+ }
+ 
+ AOTMapLogger::FakeFlatArray AOTMapLogger::FakeOop::as_flat_array() {
+   precond(real_klass()->is_flatArray_klass());
+   return FakeFlatArray(_iter, _data);
  }
  
  AOTMapLogger::FakeTypeArray AOTMapLogger::FakeOop::as_type_array() {
    precond(real_klass()->is_typeArray_klass());
    return FakeTypeArray(_iter, _data);

@@ -810,27 +854,71 @@
  }
  
  class AOTMapLogger::ArchivedFieldPrinter : public FieldClosure {
    FakeOop _fake_oop;
    outputStream* _st;
+   int _indent;
+   int _base_offset;
  public:
-   ArchivedFieldPrinter(FakeOop fake_oop, outputStream* st) : _fake_oop(fake_oop), _st(st) {}
+   ArchivedFieldPrinter(FakeOop fake_oop, outputStream* st, int indent = 1, int base_offset = 0) :
+                        _fake_oop(fake_oop), _st(st), _indent(indent), _base_offset(base_offset) {}
  
    void do_field(fieldDescriptor* fd) {
+     for (int i = 0; i < _indent; i++) _st->print("  ");
      _st->print(" - ");
+ 
+     if (_fake_oop.raw_oop() == nullptr) {
+       fd->print_on(_st, _base_offset);
+       _st->cr();
+       return;
+     }
+ 
      BasicType ft = fd->field_type();
      switch (ft) {
      case T_ARRAY:
      case T_OBJECT:
        {
-         fd->print_on(_st); // print just the name and offset
-         FakeOop field_value = _fake_oop.obj_field(fd->offset());
-         print_oop_info_cr(_st, field_value);
+         if (fd->is_flat()) {
+           int index = fd->index();
+           InlineKlass* vk = fd->field_holder()->get_inline_type_field_klass(index);
+           int field_offset = fd->offset() - vk->payload_offset();
+           address field_addr = (address)_fake_oop.buffered_field_addr(field_offset);
+           bool is_null = false;
+ 
+           if (!fd->is_null_free_inline_type()) {
+             assert(fd->has_null_marker(), "should have null marker");
+             is_null = vk->is_payload_marked_as_null(_fake_oop.buffered_addr() + fd->offset());
+             _st->print("Flat inline type field '%s':", vk->name()->as_C_string());
+           } else {
+             _st->print("Flat inline null-free type field '%s':", vk->name()->as_C_string());
+           }
+           // Print fields of flat field (recursively)
+           if (!is_null) {
+             _st->cr();
+             FakeOop obj = _fake_oop.read_inline_oop_at(field_addr, vk);
+             ArchivedFieldPrinter print_field(obj, _st, _indent + 1, _base_offset + field_offset);
+             vk->do_nonstatic_fields(&print_field);
+           } else {
+             _st->print_cr(" null");
+           }
+ 
+           if (fd->field_flags().has_null_marker()) {
+             for (int i = 0; i < _indent + 1; i++) _st->print("  ");
+             _st->print_cr(" - [null_marker] @%d %s",
+                       vk->null_marker_offset() + _base_offset + field_offset,
+                       is_null ? "Field marked as null" : "Field marked as non-null");
+           }
+           return; // Do not print underlying representation
+         } else {
+           fd->print_on(_st); // print just the name and offset
+           FakeOop field_value = _fake_oop.obj_field(fd->offset());
+           print_oop_info_cr(_st, field_value);
+         }
        }
        break;
      default:
-       _fake_oop.print_non_oop_field(_st, fd); // name, offset, value
+       _fake_oop.print_non_oop_field(_st, fd, _indent, _base_offset); // name, offset, value
        _st->cr();
      }
    }
  }; // AOTMapLogger::ArchivedFieldPrinter
  

@@ -964,12 +1052,43 @@
    st->print(" " PTR_FORMAT, p2i(fake_oop.klass().raw_addr()));
    st->cr();
  
    if (real_klass->is_typeArray_klass()) {
      fake_oop.as_type_array().print_elements_on(st);
-   } else if (real_klass->is_objArray_klass()) {
-     FakeObjArray fake_obj_array = fake_oop.as_obj_array();
+   } else if (real_klass->is_flatArray_klass()) {
+     FakeFlatArray fake_flat_array = fake_oop.as_flat_array();
+     InlineKlass* elem_k = ((FlatArrayKlass*)real_klass)->element_klass();
+     for (int i = 0; i < fake_flat_array.length(); i++) {
+       bool is_null = false;
+       int off = fake_flat_array.element_offset_at(i);
+       FakeOop elm = fake_flat_array.element_at(i);
+ 
+       if (!real_klass->is_null_free_array_klass()) {
+         is_null = elem_k->is_payload_marked_as_null(elm.buffered_addr() + elem_k->payload_offset());
+         st->print(" - Flat inline type element '%s':", elem_k->name()->as_C_string());
+       } else {
+         st->print(" - Flat inline null-free type element '%s':", elem_k->name()->as_C_string());
+       }
+       st->print(" - Index %3d offset %3d: ", i, off);
+ 
+       if (!is_null) {
+         st->cr();
+         ArchivedFieldPrinter print_field(elm, st);
+         elem_k->do_nonstatic_fields(&print_field);
+       } else {
+         assert(!real_klass->is_null_free_array_klass(), "must be");
+         st->print_cr(" null");
+       }
+ 
+       if (!real_klass->is_null_free_array_klass()) {
+         st->print_cr("   - [null_marker] @%d %s",
+                      off + elem_k->null_marker_offset_in_payload(),
+                      is_null ? "Field marked as null" : "Field marked as non-null");
+       }
+     }
+   } else if (real_klass->is_refArray_klass()) {
+     FakeRefArray fake_obj_array = fake_oop.as_ref_array();
      bool is_logging_root_segment = fake_oop.is_root_segment();
  
      for (int i = 0; i < fake_obj_array.length(); i++) {
        FakeOop elm = fake_obj_array.obj_at(i);
        if (is_logging_root_segment) {
< prev index next >