src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleWriter.cpp
branchJEP-349-branch
changeset 57870 00860d9caf4d
parent 50113 caf115bb98ad
child 57936 1b2d0f4c1e38
equal deleted inserted replaced
57862:84ef29ccac56 57870:00860d9caf4d
     1 /*
     1 /*
     2  * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     7  * published by the Free Software Foundation.
    31 #include "jfr/leakprofiler/checkpoint/objectSampleWriter.hpp"
    31 #include "jfr/leakprofiler/checkpoint/objectSampleWriter.hpp"
    32 #include "jfr/leakprofiler/checkpoint/rootResolver.hpp"
    32 #include "jfr/leakprofiler/checkpoint/rootResolver.hpp"
    33 #include "jfr/leakprofiler/sampling/objectSampler.hpp"
    33 #include "jfr/leakprofiler/sampling/objectSampler.hpp"
    34 #include "jfr/leakprofiler/utilities/rootType.hpp"
    34 #include "jfr/leakprofiler/utilities/rootType.hpp"
    35 #include "jfr/leakprofiler/utilities/unifiedOop.hpp"
    35 #include "jfr/leakprofiler/utilities/unifiedOop.hpp"
    36 #include "jfr/recorder/checkpoint/types/jfrTypeSetUtils.hpp"
    36 #include "jfr/writers/jfrTypeWriterHost.hpp"
    37 #include "jfr/recorder/checkpoint/types/jfrTypeSetWriter.hpp"
       
    38 #include "oops/oop.inline.hpp"
    37 #include "oops/oop.inline.hpp"
    39 #include "oops/symbol.hpp"
    38 #include "oops/symbol.hpp"
    40 #include "utilities/growableArray.hpp"
    39 #include "utilities/growableArray.hpp"
    41 
    40 
    42 template <typename Data>
    41 template <typename Data>
   157     assert(stored != NULL, "invariant");
   156     assert(stored != NULL, "invariant");
   158     assert(stored->_field_name_symbol->identity_hash() == query->_field_name_symbol->identity_hash(), "invariant");
   157     assert(stored->_field_name_symbol->identity_hash() == query->_field_name_symbol->identity_hash(), "invariant");
   159     return stored->_field_modifiers == query->_field_modifiers;
   158     return stored->_field_modifiers == query->_field_modifiers;
   160   }
   159   }
   161 
   160 
       
   161   void unlink(FieldInfoEntry* entry) {
       
   162     assert(entry != NULL, "invariant");
       
   163     // nothing
       
   164   }
       
   165 
   162  public:
   166  public:
   163   FieldTable() : _table(new FieldInfoTable(this)) {}
   167   FieldTable() : _table(new FieldInfoTable(this)) {}
   164   ~FieldTable() {
   168   ~FieldTable() {
   165     assert(_table != NULL, "invariant");
   169     assert(_table != NULL, "invariant");
   166     delete _table;
   170     delete _table;
   194 static RefInfo* ref_infos = NULL;
   198 static RefInfo* ref_infos = NULL;
   195 static ArrayInfo* array_infos = NULL;
   199 static ArrayInfo* array_infos = NULL;
   196 static FieldTable* field_infos = NULL;
   200 static FieldTable* field_infos = NULL;
   197 static RootDescriptionInfo* root_infos = NULL;
   201 static RootDescriptionInfo* root_infos = NULL;
   198 
   202 
   199 int __write_sample_info__(JfrCheckpointWriter* writer, JfrArtifactSet* unused, const void* si) {
   203 int __write_sample_info__(JfrCheckpointWriter* writer, const void* si) {
   200   assert(writer != NULL, "invariant");
   204   assert(writer != NULL, "invariant");
   201   assert(si != NULL, "invariant");
   205   assert(si != NULL, "invariant");
   202   const OldObjectSampleInfo* const oosi = (const OldObjectSampleInfo*)si;
   206   const OldObjectSampleInfo* const oosi = (const OldObjectSampleInfo*)si;
   203   oop object = oosi->_data._object;
   207   oop object = oosi->_data._object;
   204   assert(object != NULL, "invariant");
   208   assert(object != NULL, "invariant");
   209   writer->write(od.description());
   213   writer->write(od.description());
   210   writer->write(oosi->_data._reference_id);
   214   writer->write(oosi->_data._reference_id);
   211   return 1;
   215   return 1;
   212 }
   216 }
   213 
   217 
   214 typedef JfrArtifactWriterImplHost<const OldObjectSampleInfo*, __write_sample_info__> SampleWriterImpl;
   218 typedef JfrTypeWriterImplHost<const OldObjectSampleInfo*, __write_sample_info__> SampleWriterImpl;
   215 typedef JfrArtifactWriterHost<SampleWriterImpl, TYPE_OLDOBJECT> SampleWriter;
   219 typedef JfrTypeWriterHost<SampleWriterImpl, TYPE_OLDOBJECT> SampleWriter;
   216 
   220 
   217 static void write_sample_infos(JfrCheckpointWriter& writer) {
   221 static void write_sample_infos(JfrCheckpointWriter& writer) {
   218   if (sample_infos != NULL) {
   222   if (sample_infos != NULL) {
   219     SampleWriter sw(&writer, NULL, false);
   223     SampleWriter sw(&writer);
   220     sample_infos->iterate(sw);
   224     sample_infos->iterate(sw);
   221   }
   225   }
   222 }
   226 }
   223 
   227 
   224 int __write_reference_info__(JfrCheckpointWriter* writer, JfrArtifactSet* unused, const void* ri) {
   228 int __write_reference_info__(JfrCheckpointWriter* writer, const void* ri) {
   225   assert(writer != NULL, "invariant");
   229   assert(writer != NULL, "invariant");
   226   assert(ri != NULL, "invariant");
   230   assert(ri != NULL, "invariant");
   227   const ReferenceInfo* const ref_info = (const ReferenceInfo*)ri;
   231   const ReferenceInfo* const ref_info = (const ReferenceInfo*)ri;
   228   writer->write(ref_info->_id);
   232   writer->write(ref_info->_id);
   229   writer->write(ref_info->_data._array_info_id);
   233   writer->write(ref_info->_data._array_info_id);
   231   writer->write(ref_info->_data._old_object_sample_id);
   235   writer->write(ref_info->_data._old_object_sample_id);
   232   writer->write<s4>((s4)ref_info->_data._skip);
   236   writer->write<s4>((s4)ref_info->_data._skip);
   233   return 1;
   237   return 1;
   234 }
   238 }
   235 
   239 
   236 typedef JfrArtifactWriterImplHost<const ReferenceInfo*, __write_reference_info__> ReferenceWriterImpl;
   240 typedef JfrTypeWriterImplHost<const ReferenceInfo*, __write_reference_info__> ReferenceWriterImpl;
   237 typedef JfrArtifactWriterHost<ReferenceWriterImpl, TYPE_REFERENCE> ReferenceWriter;
   241 typedef JfrTypeWriterHost<ReferenceWriterImpl, TYPE_REFERENCE> ReferenceWriter;
   238 
   242 
   239 static void write_reference_infos(JfrCheckpointWriter& writer) {
   243 static void write_reference_infos(JfrCheckpointWriter& writer) {
   240   if (ref_infos != NULL) {
   244   if (ref_infos != NULL) {
   241     ReferenceWriter rw(&writer, NULL, false);
   245     ReferenceWriter rw(&writer);
   242     ref_infos->iterate(rw);
   246     ref_infos->iterate(rw);
   243   }
   247   }
   244 }
   248 }
   245 
   249 
   246 int __write_array_info__(JfrCheckpointWriter* writer, JfrArtifactSet* unused, const void* ai) {
   250 int __write_array_info__(JfrCheckpointWriter* writer, const void* ai) {
   247   assert(writer != NULL, "invariant");
   251   assert(writer != NULL, "invariant");
   248   assert(ai != NULL, "invariant");
   252   assert(ai != NULL, "invariant");
   249   const ObjectSampleArrayInfo* const osai = (const ObjectSampleArrayInfo*)ai;
   253   const ObjectSampleArrayInfo* const osai = (const ObjectSampleArrayInfo*)ai;
   250   writer->write(osai->_id);
   254   writer->write(osai->_id);
   251   writer->write(osai->_data._array_size);
   255   writer->write(osai->_data._array_size);
   268   osai->_data._array_size = EdgeUtils::array_size(edge);
   272   osai->_data._array_size = EdgeUtils::array_size(edge);
   269   osai->_data._array_index = EdgeUtils::array_index(edge);
   273   osai->_data._array_index = EdgeUtils::array_index(edge);
   270   return array_infos->store(osai);
   274   return array_infos->store(osai);
   271 }
   275 }
   272 
   276 
   273 typedef JfrArtifactWriterImplHost<const ObjectSampleArrayInfo*, __write_array_info__> ArrayWriterImpl;
   277 typedef JfrTypeWriterImplHost<const ObjectSampleArrayInfo*, __write_array_info__> ArrayWriterImpl;
   274 typedef JfrArtifactWriterHost<ArrayWriterImpl, TYPE_OLDOBJECTARRAY> ArrayWriter;
   278 typedef JfrTypeWriterHost<ArrayWriterImpl, TYPE_OLDOBJECTARRAY> ArrayWriter;
   275 
   279 
   276 static void write_array_infos(JfrCheckpointWriter& writer) {
   280 static void write_array_infos(JfrCheckpointWriter& writer) {
   277   if (array_infos != NULL) {
   281   if (array_infos != NULL) {
   278     ArrayWriter aw(&writer, NULL, false);
   282     ArrayWriter aw(&writer);
   279     array_infos->iterate(aw);
   283     array_infos->iterate(aw);
   280   }
   284   }
   281 }
   285 }
   282 
   286 
   283 int __write_field_info__(JfrCheckpointWriter* writer, JfrArtifactSet* unused, const void* fi) {
   287 int __write_field_info__(JfrCheckpointWriter* writer, const void* fi) {
   284   assert(writer != NULL, "invariant");
   288   assert(writer != NULL, "invariant");
   285   assert(fi != NULL, "invariant");
   289   assert(fi != NULL, "invariant");
   286   const FieldTable::FieldInfoEntry* field_info_entry = (const FieldTable::FieldInfoEntry*)fi;
   290   const FieldTable::FieldInfoEntry* field_info_entry = (const FieldTable::FieldInfoEntry*)fi;
   287   writer->write(field_info_entry->id());
   291   writer->write(field_info_entry->id());
   288   const ObjectSampleFieldInfo* const osfi = field_info_entry->literal();
   292   const ObjectSampleFieldInfo* const osfi = field_info_entry->literal();
   312   osfi->_field_name_symbol = field_name_symbol;
   316   osfi->_field_name_symbol = field_name_symbol;
   313   osfi->_field_modifiers = EdgeUtils::field_modifiers(edge);
   317   osfi->_field_modifiers = EdgeUtils::field_modifiers(edge);
   314   return field_infos->store(osfi);
   318   return field_infos->store(osfi);
   315 }
   319 }
   316 
   320 
   317 typedef JfrArtifactWriterImplHost<const FieldTable::FieldInfoEntry*, __write_field_info__> FieldWriterImpl;
   321 typedef JfrTypeWriterImplHost<const FieldTable::FieldInfoEntry*, __write_field_info__> FieldWriterImpl;
   318 typedef JfrArtifactWriterHost<FieldWriterImpl, TYPE_OLDOBJECTFIELD> FieldWriter;
   322 typedef JfrTypeWriterHost<FieldWriterImpl, TYPE_OLDOBJECTFIELD> FieldWriter;
   319 
   323 
   320 static void write_field_infos(JfrCheckpointWriter& writer) {
   324 static void write_field_infos(JfrCheckpointWriter& writer) {
   321   if (field_infos != NULL) {
   325   if (field_infos != NULL) {
   322     FieldWriter fw(&writer, NULL, false);
   326     FieldWriter fw(&writer);
   323     field_infos->iterate(fw);
   327     field_infos->iterate(fw);
   324   }
   328   }
   325 }
   329 }
   326 
   330 
   327 static const char* description(const ObjectSampleRootDescriptionInfo* osdi) {
   331 static const char* description(const ObjectSampleRootDescriptionInfo* osdi) {
   337   }
   341   }
   338   description.write_text(osdi->_data._description);
   342   description.write_text(osdi->_data._description);
   339   return description.description();
   343   return description.description();
   340 }
   344 }
   341 
   345 
   342 int __write_root_description_info__(JfrCheckpointWriter* writer, JfrArtifactSet* unused, const void* di) {
   346 int __write_root_description_info__(JfrCheckpointWriter* writer, const void* di) {
   343   assert(writer != NULL, "invariant");
   347   assert(writer != NULL, "invariant");
   344   assert(di != NULL, "invariant");
   348   assert(di != NULL, "invariant");
   345   const ObjectSampleRootDescriptionInfo* const osdi = (const ObjectSampleRootDescriptionInfo*)di;
   349   const ObjectSampleRootDescriptionInfo* const osdi = (const ObjectSampleRootDescriptionInfo*)di;
   346   writer->write(osdi->_id);
   350   writer->write(osdi->_id);
   347   writer->write(description(osdi));
   351   writer->write(description(osdi));
   348   writer->write<u8>(osdi->_data._system);
   352   writer->write<u8>(osdi->_data._system);
   349   writer->write<u8>(osdi->_data._type);
   353   writer->write<u8>(osdi->_data._type);
   350   return 1;
   354   return 1;
   351 }
   355 }
   352 
   356 
   353 static traceid get_root_description_info_id(const Edge& edge, traceid id) {
   357 static traceid get_gc_root_description_info_id(const Edge& edge, traceid id) {
   354   assert(edge.is_root(), "invariant");
   358   assert(edge.is_root(), "invariant");
   355   if (EdgeUtils::is_leak_edge(edge)) {
   359   if (EdgeUtils::is_leak_edge(edge)) {
   356     return 0;
   360     return 0;
   357   }
   361   }
   358 
   362 
   364   oodi->_id = id;
   368   oodi->_id = id;
   365   oodi->_data._root_edge = &edge;
   369   oodi->_data._root_edge = &edge;
   366   return root_infos->store(oodi);
   370   return root_infos->store(oodi);
   367 }
   371 }
   368 
   372 
   369 typedef JfrArtifactWriterImplHost<const ObjectSampleRootDescriptionInfo*, __write_root_description_info__> RootDescriptionWriterImpl;
   373 typedef JfrTypeWriterImplHost<const ObjectSampleRootDescriptionInfo*, __write_root_description_info__> RootDescriptionWriterImpl;
   370 typedef JfrArtifactWriterHost<RootDescriptionWriterImpl, TYPE_OLDOBJECTGCROOT> RootDescriptionWriter;
   374 typedef JfrTypeWriterHost<RootDescriptionWriterImpl, TYPE_OLDOBJECTGCROOT> RootDescriptionWriter;
   371 
   375 
   372 
   376 
   373 int _edge_reference_compare_(uintptr_t lhs, uintptr_t rhs) {
   377 int _edge_reference_compare_(uintptr_t lhs, uintptr_t rhs) {
   374   return lhs > rhs ? 1 : (lhs < rhs) ? -1 : 0;
   378   return lhs > rhs ? 1 : (lhs < rhs) ? -1 : 0;
   375 }
   379 }
   511   if (root_infos != NULL) {
   515   if (root_infos != NULL) {
   512     // resolve roots
   516     // resolve roots
   513     RootResolutionSet rrs(root_infos);
   517     RootResolutionSet rrs(root_infos);
   514     RootResolver::resolve(rrs);
   518     RootResolver::resolve(rrs);
   515     // write roots
   519     // write roots
   516     RootDescriptionWriter rw(&writer, NULL, false);
   520     RootDescriptionWriter rw(&writer);
   517     root_infos->iterate(rw);
   521     root_infos->iterate(rw);
   518   }
   522   }
   519 }
   523 }
   520 
   524 
   521 static void add_old_object_sample_info(const Edge* current, traceid id) {
   525 static void add_old_object_sample_info(const StoredEdge* current, traceid id) {
   522   assert(current != NULL, "invariant");
   526   assert(current != NULL, "invariant");
   523   if (sample_infos == NULL) {
   527   if (sample_infos == NULL) {
   524     sample_infos = new SampleInfo();
   528     sample_infos = new SampleInfo();
   525   }
   529   }
   526   assert(sample_infos != NULL, "invariant");
   530   assert(sample_infos != NULL, "invariant");
   527   OldObjectSampleInfo* const oosi = new OldObjectSampleInfo();
   531   OldObjectSampleInfo* const oosi = new OldObjectSampleInfo();
   528   assert(oosi != NULL, "invariant");
   532   assert(oosi != NULL, "invariant");
   529   oosi->_id = id;
   533   oosi->_id = id;
   530   oosi->_data._object = current->pointee();
   534   oosi->_data._object = current->pointee();
   531   oosi->_data._reference_id = current->is_root() ? (traceid)0 : id;
   535   oosi->_data._reference_id = current->parent() == NULL ? (traceid)0 : id;
   532   sample_infos->store(oosi);
   536   sample_infos->store(oosi);
   533 }
   537 }
   534 
   538 
   535 static void add_reference_info(const RoutableEdge* current, traceid id, traceid parent_id) {
   539 static void add_reference_info(const StoredEdge* current, traceid id, traceid parent_id) {
   536   assert(current != NULL, "invariant");
   540   assert(current != NULL, "invariant");
   537   if (ref_infos == NULL) {
   541   if (ref_infos == NULL) {
   538     ref_infos = new RefInfo();
   542     ref_infos = new RefInfo();
   539   }
   543   }
   540 
   544 
   542   ReferenceInfo* const ri = new ReferenceInfo();
   546   ReferenceInfo* const ri = new ReferenceInfo();
   543   assert(ri != NULL, "invariant");
   547   assert(ri != NULL, "invariant");
   544 
   548 
   545   ri->_id = id;
   549   ri->_id = id;
   546   ri->_data._array_info_id =  !current->is_skip_edge() ? get_array_info_id(*current, id) : 0;
   550   ri->_data._array_info_id =  !current->is_skip_edge() ? get_array_info_id(*current, id) : 0;
   547   ri->_data._field_info_id = ri->_data._array_info_id == 0 && !current->is_skip_edge() ?
   551   ri->_data._field_info_id = ri->_data._array_info_id == 0 && !current->is_skip_edge() ? get_field_info_id(*current) : (traceid)0;
   548                                get_field_info_id(*current) : (traceid)0;
       
   549   ri->_data._old_object_sample_id = parent_id;
   552   ri->_data._old_object_sample_id = parent_id;
   550   ri->_data._skip = current->skip_length();
   553   ri->_data._skip = current->skip_length();
   551   ref_infos->store(ri);
   554   ref_infos->store(ri);
   552 }
   555 }
   553 
   556 
   554 static traceid add_root_info(const Edge* root, traceid id) {
   557 static bool is_gc_root(const StoredEdge* current) {
       
   558   assert(current != NULL, "invariant");
       
   559   return current->parent() == NULL && current->gc_root_id() != 0;
       
   560 }
       
   561 
       
   562 static traceid add_gc_root_info(const StoredEdge* root, traceid id) {
   555   assert(root != NULL, "invariant");
   563   assert(root != NULL, "invariant");
   556   assert(root->is_root(), "invariant");
   564   assert(is_gc_root(root), "invariant");
   557   return get_root_description_info_id(*root, id);
   565   return get_gc_root_description_info_id(*root, id);
   558 }
   566 }
   559 
   567 
   560 void ObjectSampleWriter::write(const RoutableEdge* edge) {
   568 void ObjectSampleWriter::write(const StoredEdge* edge) {
   561   assert(edge != NULL, "invariant");
   569   assert(edge != NULL, "invariant");
   562   const traceid id = _store->get_id(edge);
   570   const traceid id = _store->get_id(edge);
   563   add_old_object_sample_info(edge, id);
   571   add_old_object_sample_info(edge, id);
   564   const RoutableEdge* parent = edge->logical_parent();
   572   const StoredEdge* const parent = edge->parent();
   565   if (parent != NULL) {
   573   if (parent != NULL) {
   566     add_reference_info(edge, id, _store->get_id(parent));
   574     add_reference_info(edge, id, _store->get_id(parent));
   567   } else {
   575   } else {
   568     assert(edge->is_root(), "invariant");
   576     if (is_gc_root(edge)) {
   569     add_root_info(edge, id);
   577       assert(edge->gc_root_id() == id, "invariant");
   570   }
   578       add_gc_root_info(edge, id);
   571 }
   579     }
   572 
   580   }
   573 ObjectSampleWriter::ObjectSampleWriter(JfrCheckpointWriter& writer, const EdgeStore* store) :
   581 }
       
   582 
       
   583 ObjectSampleWriter::ObjectSampleWriter(JfrCheckpointWriter& writer, EdgeStore* store) :
   574   _writer(writer),
   584   _writer(writer),
   575   _store(store) {
   585   _store(store) {
   576   assert(store != NULL, "invariant");
   586   assert(store != NULL, "invariant");
   577   assert(store->number_of_entries() > 0, "invariant");
   587   assert(!store->is_empty(), "invariant");
   578   sample_infos = NULL;
   588   sample_infos = NULL;
   579   ref_infos = NULL;
   589   ref_infos = NULL;
   580   array_infos = NULL;
   590   array_infos = NULL;
   581   field_infos = NULL;
   591   field_infos = NULL;
   582   root_infos = NULL;
   592   root_infos = NULL;
   588   write_array_infos(_writer);
   598   write_array_infos(_writer);
   589   write_field_infos(_writer);
   599   write_field_infos(_writer);
   590   write_root_descriptors(_writer);
   600   write_root_descriptors(_writer);
   591 }
   601 }
   592 
   602 
   593 void ObjectSampleWriter::write_chain(const RoutableEdge& edge) {
   603 bool ObjectSampleWriter::operator()(StoredEdge& e) {
   594   assert(EdgeUtils::is_leak_edge(edge), "invariant");
   604   write(&e);
   595   if (edge.processed()) {
       
   596     return;
       
   597   }
       
   598   EdgeUtils::collapse_chain(edge);
       
   599   const RoutableEdge* current = &edge;
       
   600   while (current != NULL) {
       
   601     if (current->processed()) {
       
   602       return;
       
   603     }
       
   604     write(current);
       
   605     current->set_processed();
       
   606     current = current->logical_parent();
       
   607   }
       
   608 }
       
   609 
       
   610 bool ObjectSampleWriter::operator()(const RoutableEdge& edge) {
       
   611   if (EdgeUtils::is_leak_edge(edge)) {
       
   612     write_chain(edge);
       
   613   }
       
   614   return true;
   605   return true;
   615 }
   606 }