src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleWriter.cpp
branchdatagramsocketimpl-branch
changeset 58678 9cf78a70fa4f
parent 50113 caf115bb98ad
child 58679 9c3209ff7550
equal deleted inserted replaced
58677:13588c901957 58678:9cf78a70fa4f
     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/metadata/jfrSerializer.hpp"
    37 #include "jfr/recorder/checkpoint/types/jfrTypeSetWriter.hpp"
    37 #include "jfr/writers/jfrTypeWriterHost.hpp"
    38 #include "oops/oop.inline.hpp"
    38 #include "oops/oop.inline.hpp"
    39 #include "oops/symbol.hpp"
    39 #include "oops/symbol.hpp"
    40 #include "utilities/growableArray.hpp"
    40 #include "utilities/growableArray.hpp"
    41 
    41 
    42 template <typename Data>
    42 template <typename Data>
   135             typename,
   135             typename,
   136             template<typename, typename> class,
   136             template<typename, typename> class,
   137             typename,
   137             typename,
   138             size_t>
   138             size_t>
   139   friend class HashTableHost;
   139   friend class HashTableHost;
   140   typedef HashTableHost<const ObjectSampleFieldInfo*, traceid, Entry, FieldTable, 109> FieldInfoTable;
   140   typedef HashTableHost<const ObjectSampleFieldInfo*, traceid, JfrHashtableEntry, FieldTable, 109> FieldInfoTable;
   141  public:
   141  public:
   142   typedef FieldInfoTable::HashEntry FieldInfoEntry;
   142   typedef FieldInfoTable::HashEntry FieldInfoEntry;
   143 
   143 
   144  private:
   144  private:
   145   static traceid _field_id_counter;
   145   static traceid _field_id_counter;
   146   FieldInfoTable* _table;
   146   FieldInfoTable* _table;
   147 
   147   const ObjectSampleFieldInfo* _lookup;
   148   void assign_id(FieldInfoEntry* entry) {
   148 
       
   149   void on_link(FieldInfoEntry* entry) {
   149     assert(entry != NULL, "invariant");
   150     assert(entry != NULL, "invariant");
   150     entry->set_id(++_field_id_counter);
   151     entry->set_id(++_field_id_counter);
   151   }
   152   }
   152 
   153 
   153   bool equals(const ObjectSampleFieldInfo* query, uintptr_t hash, const FieldInfoEntry* entry) {
   154   bool on_equals(uintptr_t hash, const FieldInfoEntry* entry) {
   154     assert(hash == entry->hash(), "invariant");
   155     assert(hash == entry->hash(), "invariant");
   155     assert(query != NULL, "invariant");
   156     assert(_lookup != NULL, "invariant");
   156     const ObjectSampleFieldInfo* stored = entry->literal();
   157     return entry->literal()->_field_modifiers == _lookup->_field_modifiers;
   157     assert(stored != NULL, "invariant");
   158   }
   158     assert(stored->_field_name_symbol->identity_hash() == query->_field_name_symbol->identity_hash(), "invariant");
   159 
   159     return stored->_field_modifiers == query->_field_modifiers;
   160   void on_unlink(FieldInfoEntry* entry) {
   160   }
   161     assert(entry != NULL, "invariant");
   161 
   162     // nothing
   162  public:
   163   }
   163   FieldTable() : _table(new FieldInfoTable(this)) {}
   164 
       
   165  public:
       
   166   FieldTable() : _table(new FieldInfoTable(this)), _lookup(NULL) {}
   164   ~FieldTable() {
   167   ~FieldTable() {
   165     assert(_table != NULL, "invariant");
   168     assert(_table != NULL, "invariant");
   166     delete _table;
   169     delete _table;
   167   }
   170   }
   168 
   171 
   169   traceid store(const ObjectSampleFieldInfo* field_info) {
   172   traceid store(const ObjectSampleFieldInfo* field_info) {
   170     assert(field_info != NULL, "invariant");
   173     assert(field_info != NULL, "invariant");
   171     const FieldInfoEntry& entry =_table->lookup_put(field_info,
   174     _lookup = field_info;
   172                                                     field_info->_field_name_symbol->identity_hash());
   175     const FieldInfoEntry& entry = _table->lookup_put(field_info->_field_name_symbol->identity_hash(), field_info);
   173     return entry.id();
   176     return entry.id();
   174   }
   177   }
   175 
   178 
   176   size_t size() const {
   179   size_t size() const {
   177     return _table->cardinality();
   180     return _table->cardinality();
   194 static RefInfo* ref_infos = NULL;
   197 static RefInfo* ref_infos = NULL;
   195 static ArrayInfo* array_infos = NULL;
   198 static ArrayInfo* array_infos = NULL;
   196 static FieldTable* field_infos = NULL;
   199 static FieldTable* field_infos = NULL;
   197 static RootDescriptionInfo* root_infos = NULL;
   200 static RootDescriptionInfo* root_infos = NULL;
   198 
   201 
   199 int __write_sample_info__(JfrCheckpointWriter* writer, JfrArtifactSet* unused, const void* si) {
   202 int __write_sample_info__(JfrCheckpointWriter* writer, const void* si) {
   200   assert(writer != NULL, "invariant");
   203   assert(writer != NULL, "invariant");
   201   assert(si != NULL, "invariant");
   204   assert(si != NULL, "invariant");
   202   const OldObjectSampleInfo* const oosi = (const OldObjectSampleInfo*)si;
   205   const OldObjectSampleInfo* const oosi = (const OldObjectSampleInfo*)si;
   203   oop object = oosi->_data._object;
   206   oop object = oosi->_data._object;
   204   assert(object != NULL, "invariant");
   207   assert(object != NULL, "invariant");
   209   writer->write(od.description());
   212   writer->write(od.description());
   210   writer->write(oosi->_data._reference_id);
   213   writer->write(oosi->_data._reference_id);
   211   return 1;
   214   return 1;
   212 }
   215 }
   213 
   216 
   214 typedef JfrArtifactWriterImplHost<const OldObjectSampleInfo*, __write_sample_info__> SampleWriterImpl;
   217 typedef JfrTypeWriterImplHost<const OldObjectSampleInfo*, __write_sample_info__> SampleWriterImpl;
   215 typedef JfrArtifactWriterHost<SampleWriterImpl, TYPE_OLDOBJECT> SampleWriter;
   218 typedef JfrTypeWriterHost<SampleWriterImpl, TYPE_OLDOBJECT> SampleWriter;
   216 
   219 
   217 static void write_sample_infos(JfrCheckpointWriter& writer) {
   220 static void write_sample_infos(JfrCheckpointWriter& writer) {
   218   if (sample_infos != NULL) {
   221   if (sample_infos != NULL) {
   219     SampleWriter sw(&writer, NULL, false);
   222     SampleWriter sw(&writer);
   220     sample_infos->iterate(sw);
   223     sample_infos->iterate(sw);
   221   }
   224   }
   222 }
   225 }
   223 
   226 
   224 int __write_reference_info__(JfrCheckpointWriter* writer, JfrArtifactSet* unused, const void* ri) {
   227 int __write_reference_info__(JfrCheckpointWriter* writer, const void* ri) {
   225   assert(writer != NULL, "invariant");
   228   assert(writer != NULL, "invariant");
   226   assert(ri != NULL, "invariant");
   229   assert(ri != NULL, "invariant");
   227   const ReferenceInfo* const ref_info = (const ReferenceInfo*)ri;
   230   const ReferenceInfo* const ref_info = (const ReferenceInfo*)ri;
   228   writer->write(ref_info->_id);
   231   writer->write(ref_info->_id);
   229   writer->write(ref_info->_data._array_info_id);
   232   writer->write(ref_info->_data._array_info_id);
   231   writer->write(ref_info->_data._old_object_sample_id);
   234   writer->write(ref_info->_data._old_object_sample_id);
   232   writer->write<s4>((s4)ref_info->_data._skip);
   235   writer->write<s4>((s4)ref_info->_data._skip);
   233   return 1;
   236   return 1;
   234 }
   237 }
   235 
   238 
   236 typedef JfrArtifactWriterImplHost<const ReferenceInfo*, __write_reference_info__> ReferenceWriterImpl;
   239 typedef JfrTypeWriterImplHost<const ReferenceInfo*, __write_reference_info__> ReferenceWriterImpl;
   237 typedef JfrArtifactWriterHost<ReferenceWriterImpl, TYPE_REFERENCE> ReferenceWriter;
   240 typedef JfrTypeWriterHost<ReferenceWriterImpl, TYPE_REFERENCE> ReferenceWriter;
   238 
   241 
   239 static void write_reference_infos(JfrCheckpointWriter& writer) {
   242 static void write_reference_infos(JfrCheckpointWriter& writer) {
   240   if (ref_infos != NULL) {
   243   if (ref_infos != NULL) {
   241     ReferenceWriter rw(&writer, NULL, false);
   244     ReferenceWriter rw(&writer);
   242     ref_infos->iterate(rw);
   245     ref_infos->iterate(rw);
   243   }
   246   }
   244 }
   247 }
   245 
   248 
   246 int __write_array_info__(JfrCheckpointWriter* writer, JfrArtifactSet* unused, const void* ai) {
   249 int __write_array_info__(JfrCheckpointWriter* writer, const void* ai) {
   247   assert(writer != NULL, "invariant");
   250   assert(writer != NULL, "invariant");
   248   assert(ai != NULL, "invariant");
   251   assert(ai != NULL, "invariant");
   249   const ObjectSampleArrayInfo* const osai = (const ObjectSampleArrayInfo*)ai;
   252   const ObjectSampleArrayInfo* const osai = (const ObjectSampleArrayInfo*)ai;
   250   writer->write(osai->_id);
   253   writer->write(osai->_id);
   251   writer->write(osai->_data._array_size);
   254   writer->write(osai->_data._array_size);
   268   osai->_data._array_size = EdgeUtils::array_size(edge);
   271   osai->_data._array_size = EdgeUtils::array_size(edge);
   269   osai->_data._array_index = EdgeUtils::array_index(edge);
   272   osai->_data._array_index = EdgeUtils::array_index(edge);
   270   return array_infos->store(osai);
   273   return array_infos->store(osai);
   271 }
   274 }
   272 
   275 
   273 typedef JfrArtifactWriterImplHost<const ObjectSampleArrayInfo*, __write_array_info__> ArrayWriterImpl;
   276 typedef JfrTypeWriterImplHost<const ObjectSampleArrayInfo*, __write_array_info__> ArrayWriterImpl;
   274 typedef JfrArtifactWriterHost<ArrayWriterImpl, TYPE_OLDOBJECTARRAY> ArrayWriter;
   277 typedef JfrTypeWriterHost<ArrayWriterImpl, TYPE_OLDOBJECTARRAY> ArrayWriter;
   275 
   278 
   276 static void write_array_infos(JfrCheckpointWriter& writer) {
   279 static void write_array_infos(JfrCheckpointWriter& writer) {
   277   if (array_infos != NULL) {
   280   if (array_infos != NULL) {
   278     ArrayWriter aw(&writer, NULL, false);
   281     ArrayWriter aw(&writer);
   279     array_infos->iterate(aw);
   282     array_infos->iterate(aw);
   280   }
   283   }
   281 }
   284 }
   282 
   285 
   283 int __write_field_info__(JfrCheckpointWriter* writer, JfrArtifactSet* unused, const void* fi) {
   286 int __write_field_info__(JfrCheckpointWriter* writer, const void* fi) {
   284   assert(writer != NULL, "invariant");
   287   assert(writer != NULL, "invariant");
   285   assert(fi != NULL, "invariant");
   288   assert(fi != NULL, "invariant");
   286   const FieldTable::FieldInfoEntry* field_info_entry = (const FieldTable::FieldInfoEntry*)fi;
   289   const FieldTable::FieldInfoEntry* field_info_entry = (const FieldTable::FieldInfoEntry*)fi;
   287   writer->write(field_info_entry->id());
   290   writer->write(field_info_entry->id());
   288   const ObjectSampleFieldInfo* const osfi = field_info_entry->literal();
   291   const ObjectSampleFieldInfo* const osfi = field_info_entry->literal();
   312   osfi->_field_name_symbol = field_name_symbol;
   315   osfi->_field_name_symbol = field_name_symbol;
   313   osfi->_field_modifiers = EdgeUtils::field_modifiers(edge);
   316   osfi->_field_modifiers = EdgeUtils::field_modifiers(edge);
   314   return field_infos->store(osfi);
   317   return field_infos->store(osfi);
   315 }
   318 }
   316 
   319 
   317 typedef JfrArtifactWriterImplHost<const FieldTable::FieldInfoEntry*, __write_field_info__> FieldWriterImpl;
   320 typedef JfrTypeWriterImplHost<const FieldTable::FieldInfoEntry*, __write_field_info__> FieldWriterImpl;
   318 typedef JfrArtifactWriterHost<FieldWriterImpl, TYPE_OLDOBJECTFIELD> FieldWriter;
   321 typedef JfrTypeWriterHost<FieldWriterImpl, TYPE_OLDOBJECTFIELD> FieldWriter;
   319 
   322 
   320 static void write_field_infos(JfrCheckpointWriter& writer) {
   323 static void write_field_infos(JfrCheckpointWriter& writer) {
   321   if (field_infos != NULL) {
   324   if (field_infos != NULL) {
   322     FieldWriter fw(&writer, NULL, false);
   325     FieldWriter fw(&writer);
   323     field_infos->iterate(fw);
   326     field_infos->iterate(fw);
   324   }
   327   }
   325 }
   328 }
   326 
   329 
   327 static const char* description(const ObjectSampleRootDescriptionInfo* osdi) {
   330 static const char* description(const ObjectSampleRootDescriptionInfo* osdi) {
   337   }
   340   }
   338   description.write_text(osdi->_data._description);
   341   description.write_text(osdi->_data._description);
   339   return description.description();
   342   return description.description();
   340 }
   343 }
   341 
   344 
   342 int __write_root_description_info__(JfrCheckpointWriter* writer, JfrArtifactSet* unused, const void* di) {
   345 int __write_root_description_info__(JfrCheckpointWriter* writer, const void* di) {
   343   assert(writer != NULL, "invariant");
   346   assert(writer != NULL, "invariant");
   344   assert(di != NULL, "invariant");
   347   assert(di != NULL, "invariant");
   345   const ObjectSampleRootDescriptionInfo* const osdi = (const ObjectSampleRootDescriptionInfo*)di;
   348   const ObjectSampleRootDescriptionInfo* const osdi = (const ObjectSampleRootDescriptionInfo*)di;
   346   writer->write(osdi->_id);
   349   writer->write(osdi->_id);
   347   writer->write(description(osdi));
   350   writer->write(description(osdi));
   348   writer->write<u8>(osdi->_data._system);
   351   writer->write<u8>(osdi->_data._system);
   349   writer->write<u8>(osdi->_data._type);
   352   writer->write<u8>(osdi->_data._type);
   350   return 1;
   353   return 1;
   351 }
   354 }
   352 
   355 
   353 static traceid get_root_description_info_id(const Edge& edge, traceid id) {
   356 static traceid get_gc_root_description_info_id(const Edge& edge, traceid id) {
   354   assert(edge.is_root(), "invariant");
   357   assert(edge.is_root(), "invariant");
   355   if (EdgeUtils::is_leak_edge(edge)) {
   358   if (EdgeUtils::is_leak_edge(edge)) {
   356     return 0;
   359     return 0;
   357   }
   360   }
   358 
   361 
   364   oodi->_id = id;
   367   oodi->_id = id;
   365   oodi->_data._root_edge = &edge;
   368   oodi->_data._root_edge = &edge;
   366   return root_infos->store(oodi);
   369   return root_infos->store(oodi);
   367 }
   370 }
   368 
   371 
   369 typedef JfrArtifactWriterImplHost<const ObjectSampleRootDescriptionInfo*, __write_root_description_info__> RootDescriptionWriterImpl;
   372 typedef JfrTypeWriterImplHost<const ObjectSampleRootDescriptionInfo*, __write_root_description_info__> RootDescriptionWriterImpl;
   370 typedef JfrArtifactWriterHost<RootDescriptionWriterImpl, TYPE_OLDOBJECTGCROOT> RootDescriptionWriter;
   373 typedef JfrTypeWriterHost<RootDescriptionWriterImpl, TYPE_OLDOBJECTGCROOT> RootDescriptionWriter;
   371 
   374 
   372 
   375 
   373 int _edge_reference_compare_(uintptr_t lhs, uintptr_t rhs) {
   376 int _edge_reference_compare_(uintptr_t lhs, uintptr_t rhs) {
   374   return lhs > rhs ? 1 : (lhs < rhs) ? -1 : 0;
   377   return lhs > rhs ? 1 : (lhs < rhs) ? -1 : 0;
   375 }
   378 }
   511   if (root_infos != NULL) {
   514   if (root_infos != NULL) {
   512     // resolve roots
   515     // resolve roots
   513     RootResolutionSet rrs(root_infos);
   516     RootResolutionSet rrs(root_infos);
   514     RootResolver::resolve(rrs);
   517     RootResolver::resolve(rrs);
   515     // write roots
   518     // write roots
   516     RootDescriptionWriter rw(&writer, NULL, false);
   519     RootDescriptionWriter rw(&writer);
   517     root_infos->iterate(rw);
   520     root_infos->iterate(rw);
   518   }
   521   }
   519 }
   522 }
   520 
   523 
   521 static void add_old_object_sample_info(const Edge* current, traceid id) {
   524 static void add_old_object_sample_info(const StoredEdge* current, traceid id) {
   522   assert(current != NULL, "invariant");
   525   assert(current != NULL, "invariant");
   523   if (sample_infos == NULL) {
   526   if (sample_infos == NULL) {
   524     sample_infos = new SampleInfo();
   527     sample_infos = new SampleInfo();
   525   }
   528   }
   526   assert(sample_infos != NULL, "invariant");
   529   assert(sample_infos != NULL, "invariant");
   527   OldObjectSampleInfo* const oosi = new OldObjectSampleInfo();
   530   OldObjectSampleInfo* const oosi = new OldObjectSampleInfo();
   528   assert(oosi != NULL, "invariant");
   531   assert(oosi != NULL, "invariant");
   529   oosi->_id = id;
   532   oosi->_id = id;
   530   oosi->_data._object = current->pointee();
   533   oosi->_data._object = current->pointee();
   531   oosi->_data._reference_id = current->is_root() ? (traceid)0 : id;
   534   oosi->_data._reference_id = current->parent() == NULL ? (traceid)0 : id;
   532   sample_infos->store(oosi);
   535   sample_infos->store(oosi);
   533 }
   536 }
   534 
   537 
   535 static void add_reference_info(const RoutableEdge* current, traceid id, traceid parent_id) {
   538 static void add_reference_info(const StoredEdge* current, traceid id, traceid parent_id) {
   536   assert(current != NULL, "invariant");
   539   assert(current != NULL, "invariant");
   537   if (ref_infos == NULL) {
   540   if (ref_infos == NULL) {
   538     ref_infos = new RefInfo();
   541     ref_infos = new RefInfo();
   539   }
   542   }
   540 
   543 
   542   ReferenceInfo* const ri = new ReferenceInfo();
   545   ReferenceInfo* const ri = new ReferenceInfo();
   543   assert(ri != NULL, "invariant");
   546   assert(ri != NULL, "invariant");
   544 
   547 
   545   ri->_id = id;
   548   ri->_id = id;
   546   ri->_data._array_info_id =  !current->is_skip_edge() ? get_array_info_id(*current, id) : 0;
   549   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() ?
   550   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;
   551   ri->_data._old_object_sample_id = parent_id;
   550   ri->_data._skip = current->skip_length();
   552   ri->_data._skip = current->skip_length();
   551   ref_infos->store(ri);
   553   ref_infos->store(ri);
   552 }
   554 }
   553 
   555 
   554 static traceid add_root_info(const Edge* root, traceid id) {
   556 static bool is_gc_root(const StoredEdge* current) {
       
   557   assert(current != NULL, "invariant");
       
   558   return current->parent() == NULL && current->gc_root_id() != 0;
       
   559 }
       
   560 
       
   561 static traceid add_gc_root_info(const StoredEdge* root, traceid id) {
   555   assert(root != NULL, "invariant");
   562   assert(root != NULL, "invariant");
   556   assert(root->is_root(), "invariant");
   563   assert(is_gc_root(root), "invariant");
   557   return get_root_description_info_id(*root, id);
   564   return get_gc_root_description_info_id(*root, id);
   558 }
   565 }
   559 
   566 
   560 void ObjectSampleWriter::write(const RoutableEdge* edge) {
   567 void ObjectSampleWriter::write(const StoredEdge* edge) {
   561   assert(edge != NULL, "invariant");
   568   assert(edge != NULL, "invariant");
   562   const traceid id = _store->get_id(edge);
   569   const traceid id = _store->get_id(edge);
   563   add_old_object_sample_info(edge, id);
   570   add_old_object_sample_info(edge, id);
   564   const RoutableEdge* parent = edge->logical_parent();
   571   const StoredEdge* const parent = edge->parent();
   565   if (parent != NULL) {
   572   if (parent != NULL) {
   566     add_reference_info(edge, id, _store->get_id(parent));
   573     add_reference_info(edge, id, _store->get_id(parent));
   567   } else {
   574   } else {
   568     assert(edge->is_root(), "invariant");
   575     if (is_gc_root(edge)) {
   569     add_root_info(edge, id);
   576       assert(edge->gc_root_id() == id, "invariant");
   570   }
   577       add_gc_root_info(edge, id);
   571 }
   578     }
   572 
   579   }
   573 ObjectSampleWriter::ObjectSampleWriter(JfrCheckpointWriter& writer, const EdgeStore* store) :
   580 }
       
   581 
       
   582 class RootSystemType : public JfrSerializer {
       
   583  public:
       
   584   void serialize(JfrCheckpointWriter& writer) {
       
   585     const u4 nof_root_systems = OldObjectRoot::_number_of_systems;
       
   586     writer.write_count(nof_root_systems);
       
   587     for (u4 i = 0; i < nof_root_systems; ++i) {
       
   588       writer.write_key(i);
       
   589       writer.write(OldObjectRoot::system_description((OldObjectRoot::System)i));
       
   590     }
       
   591   }
       
   592 };
       
   593 
       
   594 class RootType : public JfrSerializer {
       
   595  public:
       
   596   void serialize(JfrCheckpointWriter& writer) {
       
   597     const u4 nof_root_types = OldObjectRoot::_number_of_types;
       
   598     writer.write_count(nof_root_types);
       
   599     for (u4 i = 0; i < nof_root_types; ++i) {
       
   600       writer.write_key(i);
       
   601       writer.write(OldObjectRoot::type_description((OldObjectRoot::Type)i));
       
   602     }
       
   603   }
       
   604 };
       
   605 
       
   606 static void register_serializers() {
       
   607   static bool is_registered = false;
       
   608   if (!is_registered) {
       
   609     JfrSerializer::register_serializer(TYPE_OLDOBJECTROOTSYSTEM, false, true, new RootSystemType());
       
   610     JfrSerializer::register_serializer(TYPE_OLDOBJECTROOTTYPE, false, true, new RootType());
       
   611     is_registered = true;
       
   612   }
       
   613 }
       
   614 
       
   615 ObjectSampleWriter::ObjectSampleWriter(JfrCheckpointWriter& writer, EdgeStore* store) :
   574   _writer(writer),
   616   _writer(writer),
   575   _store(store) {
   617   _store(store) {
   576   assert(store != NULL, "invariant");
   618   assert(store != NULL, "invariant");
   577   assert(store->number_of_entries() > 0, "invariant");
   619   assert(!store->is_empty(), "invariant");
       
   620   register_serializers();
   578   sample_infos = NULL;
   621   sample_infos = NULL;
   579   ref_infos = NULL;
   622   ref_infos = NULL;
   580   array_infos = NULL;
   623   array_infos = NULL;
   581   field_infos = NULL;
   624   field_infos = NULL;
   582   root_infos = NULL;
   625   root_infos = NULL;
   588   write_array_infos(_writer);
   631   write_array_infos(_writer);
   589   write_field_infos(_writer);
   632   write_field_infos(_writer);
   590   write_root_descriptors(_writer);
   633   write_root_descriptors(_writer);
   591 }
   634 }
   592 
   635 
   593 void ObjectSampleWriter::write_chain(const RoutableEdge& edge) {
   636 bool ObjectSampleWriter::operator()(StoredEdge& e) {
   594   assert(EdgeUtils::is_leak_edge(edge), "invariant");
   637   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;
   638   return true;
   615 }
   639 }