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)); |
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 StoredEdge* current, traceid id) { |
524 static void add_old_object_sample_info(const StoredEdge* current, traceid id) { |
574 add_gc_root_info(edge, id); |
577 add_gc_root_info(edge, id); |
575 } |
578 } |
576 } |
579 } |
577 } |
580 } |
578 |
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 |
579 ObjectSampleWriter::ObjectSampleWriter(JfrCheckpointWriter& writer, EdgeStore* store) : |
615 ObjectSampleWriter::ObjectSampleWriter(JfrCheckpointWriter& writer, EdgeStore* store) : |
580 _writer(writer), |
616 _writer(writer), |
581 _store(store) { |
617 _store(store) { |
582 assert(store != NULL, "invariant"); |
618 assert(store != NULL, "invariant"); |
583 assert(!store->is_empty(), "invariant"); |
619 assert(!store->is_empty(), "invariant"); |
|
620 register_serializers(); |
584 sample_infos = NULL; |
621 sample_infos = NULL; |
585 ref_infos = NULL; |
622 ref_infos = NULL; |
586 array_infos = NULL; |
623 array_infos = NULL; |
587 field_infos = NULL; |
624 field_infos = NULL; |
588 root_infos = NULL; |
625 root_infos = NULL; |