< prev index next > src/hotspot/share/cds/aotMapLogger.cpp
Print this page
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*)
//
// 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();
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:
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) {}
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);
}
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
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 >