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. |
516 RootDescriptionWriter rw(&writer, NULL, false); |
516 RootDescriptionWriter rw(&writer, NULL, false); |
517 root_infos->iterate(rw); |
517 root_infos->iterate(rw); |
518 } |
518 } |
519 } |
519 } |
520 |
520 |
521 static void add_old_object_sample_info(const Edge* current, traceid id) { |
521 static void add_old_object_sample_info(const StoredEdge* current, traceid id) { |
522 assert(current != NULL, "invariant"); |
522 assert(current != NULL, "invariant"); |
523 if (sample_infos == NULL) { |
523 if (sample_infos == NULL) { |
524 sample_infos = new SampleInfo(); |
524 sample_infos = new SampleInfo(); |
525 } |
525 } |
526 assert(sample_infos != NULL, "invariant"); |
526 assert(sample_infos != NULL, "invariant"); |
527 OldObjectSampleInfo* const oosi = new OldObjectSampleInfo(); |
527 OldObjectSampleInfo* const oosi = new OldObjectSampleInfo(); |
528 assert(oosi != NULL, "invariant"); |
528 assert(oosi != NULL, "invariant"); |
529 oosi->_id = id; |
529 oosi->_id = id; |
530 oosi->_data._object = current->pointee(); |
530 oosi->_data._object = current->pointee(); |
531 oosi->_data._reference_id = current->is_root() ? (traceid)0 : id; |
531 oosi->_data._reference_id = current->parent() == NULL ? (traceid)0 : id; |
532 sample_infos->store(oosi); |
532 sample_infos->store(oosi); |
533 } |
533 } |
534 |
534 |
535 static void add_reference_info(const RoutableEdge* current, traceid id, traceid parent_id) { |
535 static void add_reference_info(const StoredEdge* current, traceid id, traceid parent_id) { |
536 assert(current != NULL, "invariant"); |
536 assert(current != NULL, "invariant"); |
537 if (ref_infos == NULL) { |
537 if (ref_infos == NULL) { |
538 ref_infos = new RefInfo(); |
538 ref_infos = new RefInfo(); |
539 } |
539 } |
540 |
540 |
542 ReferenceInfo* const ri = new ReferenceInfo(); |
542 ReferenceInfo* const ri = new ReferenceInfo(); |
543 assert(ri != NULL, "invariant"); |
543 assert(ri != NULL, "invariant"); |
544 |
544 |
545 ri->_id = id; |
545 ri->_id = id; |
546 ri->_data._array_info_id = !current->is_skip_edge() ? get_array_info_id(*current, id) : 0; |
546 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() ? |
547 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; |
548 ri->_data._old_object_sample_id = parent_id; |
550 ri->_data._skip = current->skip_length(); |
549 ri->_data._skip = current->skip_length(); |
551 ref_infos->store(ri); |
550 ref_infos->store(ri); |
552 } |
551 } |
553 |
552 |
554 static traceid add_root_info(const Edge* root, traceid id) { |
553 static bool is_gc_root(const StoredEdge* current) { |
|
554 assert(current != NULL, "invariant"); |
|
555 return current->parent() == NULL && current->gc_root_id() != 0; |
|
556 } |
|
557 |
|
558 static traceid add_gc_root_info(const StoredEdge* root, traceid id) { |
555 assert(root != NULL, "invariant"); |
559 assert(root != NULL, "invariant"); |
556 assert(root->is_root(), "invariant"); |
560 assert(is_gc_root(root), "invariant"); |
557 return get_root_description_info_id(*root, id); |
561 return get_gc_root_description_info_id(*root, id); |
558 } |
562 } |
559 |
563 |
560 void ObjectSampleWriter::write(const RoutableEdge* edge) { |
564 void ObjectSampleWriter::write(const StoredEdge* edge) { |
561 assert(edge != NULL, "invariant"); |
565 assert(edge != NULL, "invariant"); |
562 const traceid id = _store->get_id(edge); |
566 const traceid id = _store->get_id(edge); |
563 add_old_object_sample_info(edge, id); |
567 add_old_object_sample_info(edge, id); |
564 const RoutableEdge* parent = edge->logical_parent(); |
568 const StoredEdge* const parent = edge->parent(); |
565 if (parent != NULL) { |
569 if (parent != NULL) { |
566 add_reference_info(edge, id, _store->get_id(parent)); |
570 add_reference_info(edge, id, _store->get_id(parent)); |
567 } else { |
571 } else { |
568 assert(edge->is_root(), "invariant"); |
572 if (is_gc_root(edge)) { |
569 add_root_info(edge, id); |
573 assert(edge->gc_root_id() == id, "invariant"); |
570 } |
574 add_gc_root_info(edge, id); |
571 } |
575 } |
572 |
576 } |
573 ObjectSampleWriter::ObjectSampleWriter(JfrCheckpointWriter& writer, const EdgeStore* store) : |
577 } |
|
578 |
|
579 ObjectSampleWriter::ObjectSampleWriter(JfrCheckpointWriter& writer, EdgeStore* store) : |
574 _writer(writer), |
580 _writer(writer), |
575 _store(store) { |
581 _store(store) { |
576 assert(store != NULL, "invariant"); |
582 assert(store != NULL, "invariant"); |
577 assert(store->number_of_entries() > 0, "invariant"); |
583 assert(!store->is_empty(), "invariant"); |
578 sample_infos = NULL; |
584 sample_infos = NULL; |
579 ref_infos = NULL; |
585 ref_infos = NULL; |
580 array_infos = NULL; |
586 array_infos = NULL; |
581 field_infos = NULL; |
587 field_infos = NULL; |
582 root_infos = NULL; |
588 root_infos = NULL; |
588 write_array_infos(_writer); |
594 write_array_infos(_writer); |
589 write_field_infos(_writer); |
595 write_field_infos(_writer); |
590 write_root_descriptors(_writer); |
596 write_root_descriptors(_writer); |
591 } |
597 } |
592 |
598 |
593 void ObjectSampleWriter::write_chain(const RoutableEdge& edge) { |
599 bool ObjectSampleWriter::operator()(StoredEdge& e) { |
594 assert(EdgeUtils::is_leak_edge(edge), "invariant"); |
600 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; |
601 return true; |
615 } |
602 } |