20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #include "cds/cdsConfig.hpp"
26 #include "ci/ciEnv.hpp"
27 #include "ci/ciMetadata.hpp"
28 #include "classfile/classLoaderData.hpp"
29 #include "classfile/compactHashtable.hpp"
30 #include "classfile/javaClasses.hpp"
31 #include "classfile/symbolTable.hpp"
32 #include "classfile/systemDictionaryShared.hpp"
33 #include "compiler/compileTask.hpp"
34 #include "memory/metadataFactory.hpp"
35 #include "memory/metaspaceClosure.hpp"
36 #include "memory/resourceArea.hpp"
37 #include "memory/universe.hpp"
38 #include "oops/method.hpp"
39 #include "oops/methodCounters.hpp"
40 #include "oops/trainingData.hpp"
41 #include "runtime/arguments.hpp"
42 #include "runtime/javaThread.inline.hpp"
43 #include "runtime/jniHandles.inline.hpp"
44 #include "utilities/growableArray.hpp"
45
46 TrainingData::TrainingDataSet TrainingData::_training_data_set(1024, 0x3fffffff);
47 TrainingData::TrainingDataDictionary TrainingData::_archived_training_data_dictionary;
48 TrainingData::TrainingDataDictionary TrainingData::_archived_training_data_dictionary_for_dumping;
49 TrainingData::DumptimeTrainingDataDictionary* TrainingData::_dumptime_training_data_dictionary = nullptr;
50 int TrainingData::TrainingDataLocker::_lock_mode;
51 volatile bool TrainingData::TrainingDataLocker::_snapshot = false;
52
53 MethodTrainingData::MethodTrainingData() {
54 // Used by cppVtables.cpp only
55 assert(CDSConfig::is_dumping_static_archive() || UseSharedSpaces, "only for CDS");
56 }
57
58 KlassTrainingData::KlassTrainingData() {
59 // Used by cppVtables.cpp only
60 assert(CDSConfig::is_dumping_static_archive() || UseSharedSpaces, "only for CDS");
61 }
62
63 CompileTrainingData::CompileTrainingData() : _level(-1), _compile_id(-1) {
64 // Used by cppVtables.cpp only
65 assert(CDSConfig::is_dumping_static_archive() || UseSharedSpaces, "only for CDS");
66 }
67
68 void TrainingData::initialize() {
69 // this is a nop if training modes are not enabled
70 if (have_data() || need_data()) {
71 // Data structures that we have do not currently support iterative training. So you cannot replay
72 // and train at the same time. Going forward we may want to adjust iteration/search to enable that.
73 guarantee(have_data() != need_data(), "Iterative training is not supported");
74 TrainingDataLocker::initialize();
75 }
76 }
77
78 static void verify_archived_entry(TrainingData* td, const TrainingData::Key* k) {
79 guarantee(TrainingData::Key::can_compute_cds_hash(k), "");
80 TrainingData* td1 = TrainingData::lookup_archived_training_data(k);
81 guarantee(td == td1, "");
82 }
83
84 void TrainingData::verify() {
85 if (TrainingData::have_data() && !TrainingData::assembling_data()) {
86 archived_training_data_dictionary()->iterate([&](TrainingData* td) {
87 if (td->is_KlassTrainingData()) {
88 KlassTrainingData* ktd = td->as_KlassTrainingData();
89 if (ktd->has_holder() && ktd->holder()->is_loaded()) {
90 Key k(ktd->holder());
91 verify_archived_entry(td, &k);
92 }
93 ktd->verify();
94 } else if (td->is_MethodTrainingData()) {
95 MethodTrainingData* mtd = td->as_MethodTrainingData();
472 _dumptime_training_data_dictionary = new DumptimeTrainingDataDictionary();
473 _archived_training_data_dictionary.iterate([&](TrainingData* record) {
474 _dumptime_training_data_dictionary->append(record);
475 });
476 }
477 if (need_data()) {
478 _dumptime_training_data_dictionary = new DumptimeTrainingDataDictionary();
479 TrainingDataLocker l;
480 TrainingDataLocker::snapshot();
481
482 ResourceMark rm;
483 Visitor visitor(training_data_set()->size());
484 training_data_set()->iterate([&](TrainingData* td) {
485 td->prepare(visitor);
486 if (!td->is_CompileTrainingData()) {
487 _dumptime_training_data_dictionary->append(td);
488 }
489 });
490 }
491
492 if (AOTVerifyTrainingData) {
493 TrainingData::verify();
494 }
495 }
496
497 void TrainingData::iterate_roots(MetaspaceClosure* it) {
498 if (_dumptime_training_data_dictionary != nullptr) {
499 for (int i = 0; i < _dumptime_training_data_dictionary->length(); i++) {
500 _dumptime_training_data_dictionary->at(i).metaspace_pointers_do(it);
501 }
502 }
503 }
504
505 void TrainingData::dump_training_data() {
506 if (_dumptime_training_data_dictionary != nullptr) {
507 CompactHashtableStats stats;
508 _archived_training_data_dictionary_for_dumping.reset();
509 CompactHashtableWriter writer(_dumptime_training_data_dictionary->length(), &stats);
510 for (int i = 0; i < _dumptime_training_data_dictionary->length(); i++) {
511 TrainingData* td = _dumptime_training_data_dictionary->at(i).training_data();
512 #ifdef ASSERT
513 for (int j = i+1; j < _dumptime_training_data_dictionary->length(); j++) {
514 TrainingData* td1 = _dumptime_training_data_dictionary->at(j).training_data();
515 assert(!TrainingData::Key::equals(td1, td->key(), -1), "conflict");
516 }
517 #endif // ASSERT
518 td = ArchiveBuilder::current()->get_buffered_addr(td);
519 uint hash = TrainingData::Key::cds_hash(td->key());
520 u4 delta = ArchiveBuilder::current()->buffer_to_offset_u4((address)td);
521 writer.add(hash, delta);
522 }
529 ResourceMark rm;
530 Visitor visitor(_dumptime_training_data_dictionary->length());
531 for (int i = 0; i < _dumptime_training_data_dictionary->length(); i++) {
532 TrainingData* td = _dumptime_training_data_dictionary->at(i).training_data();
533 td->cleanup(visitor);
534 }
535 // Throw away all elements with empty keys
536 int j = 0;
537 for (int i = 0; i < _dumptime_training_data_dictionary->length(); i++) {
538 TrainingData* td = _dumptime_training_data_dictionary->at(i).training_data();
539 if (td->key()->is_empty()) {
540 continue;
541 }
542 if (i != j) { // no need to copy if it's the same
543 _dumptime_training_data_dictionary->at_put(j, td);
544 }
545 j++;
546 }
547 _dumptime_training_data_dictionary->trunc_to(j);
548 }
549 }
550
551 void KlassTrainingData::cleanup(Visitor& visitor) {
552 if (visitor.is_visited(this)) {
553 return;
554 }
555 visitor.visit(this);
556 if (has_holder()) {
557 bool is_excluded = !holder()->is_loaded() || SystemDictionaryShared::check_for_exclusion(holder(), nullptr);
558 if (is_excluded) {
559 ResourceMark rm;
560 log_debug(aot, training)("Cleanup KTD %s", name()->as_klass_external_name());
561 _holder = nullptr;
562 key()->make_empty();
563 }
564 }
565 for (int i = 0; i < _comp_deps.length(); i++) {
566 _comp_deps.at(i)->cleanup(visitor);
567 }
568 }
637 tty->cr();
638 }
639 guarantee(invariant, "init deps invariant violation: %d >= %d", init_deps_left1, init_deps_left2);
640 }
641 }
642
643 void CompileTrainingData::cleanup(Visitor& visitor) {
644 if (visitor.is_visited(this)) {
645 return;
646 }
647 visitor.visit(this);
648 method()->cleanup(visitor);
649 }
650
651 void TrainingData::serialize(SerializeClosure* soc) {
652 if (soc->writing()) {
653 _archived_training_data_dictionary_for_dumping.serialize_header(soc);
654 } else {
655 _archived_training_data_dictionary.serialize_header(soc);
656 }
657 }
658
659 class TrainingDataPrinter : StackObj {
660 outputStream* _st;
661 int _index;
662 public:
663 TrainingDataPrinter(outputStream* st) : _st(st), _index(0) {}
664 void do_value(TrainingData* td) {
665 const char* type = (td->is_KlassTrainingData() ? "K" :
666 td->is_MethodTrainingData() ? "M" :
667 td->is_CompileTrainingData() ? "C" : "?");
668 _st->print("%4d: %p %s ", _index++, td, type);
669 td->print_on(_st);
670 _st->cr();
671 if (td->is_KlassTrainingData()) {
672 td->as_KlassTrainingData()->iterate_comp_deps([&](CompileTrainingData* ctd) {
673 ResourceMark rm;
674 _st->print_raw(" C ");
675 ctd->print_on(_st);
676 _st->cr();
677 });
678 } else if (td->is_MethodTrainingData()) {
679 td->as_MethodTrainingData()->iterate_compiles([&](CompileTrainingData* ctd) {
680 ResourceMark rm;
681 _st->print_raw(" C ");
682 ctd->print_on(_st);
683 _st->cr();
684 });
685 } else if (td->is_CompileTrainingData()) {
686 // ?
687 }
688 }
689 };
690
691 void TrainingData::print_archived_training_data_on(outputStream* st) {
692 st->print_cr("Archived TrainingData Dictionary");
693 TrainingDataPrinter tdp(st);
694 TrainingDataLocker::initialize();
695 _archived_training_data_dictionary.iterate(&tdp);
696 }
697
698 void TrainingData::Key::metaspace_pointers_do(MetaspaceClosure *iter) {
699 iter->push(const_cast<Metadata**>(&_meta));
700 }
701
702 void TrainingData::metaspace_pointers_do(MetaspaceClosure* iter) {
703 _key.metaspace_pointers_do(iter);
704 }
705
706 bool TrainingData::Key::can_compute_cds_hash(const Key* const& k) {
707 return k->meta() == nullptr || MetaspaceObj::in_aot_cache(k->meta());
708 }
709
710 uint TrainingData::Key::cds_hash(const Key* const& k) {
711 return SystemDictionaryShared::hash_for_shared_dictionary((address)k->meta());
712 }
713
714 TrainingData* TrainingData::lookup_archived_training_data(const Key* k) {
715 // For this to work, all components of the key must be in shared metaspace.
|
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #include "cds/cdsConfig.hpp"
26 #include "ci/ciEnv.hpp"
27 #include "ci/ciMetadata.hpp"
28 #include "classfile/classLoaderData.hpp"
29 #include "classfile/compactHashtable.hpp"
30 #include "classfile/javaClasses.hpp"
31 #include "classfile/symbolTable.hpp"
32 #include "classfile/systemDictionaryShared.hpp"
33 #include "compiler/compileTask.hpp"
34 #include "memory/metadataFactory.hpp"
35 #include "memory/metaspaceClosure.hpp"
36 #include "memory/resourceArea.hpp"
37 #include "memory/universe.hpp"
38 #include "oops/method.hpp"
39 #include "oops/methodCounters.hpp"
40 #include "oops/recompilationSchedule.hpp"
41 #include "oops/trainingData.hpp"
42 #include "runtime/arguments.hpp"
43 #include "runtime/javaThread.inline.hpp"
44 #include "runtime/jniHandles.inline.hpp"
45 #include "utilities/growableArray.hpp"
46
47 TrainingData::TrainingDataSet TrainingData::_training_data_set(1024, 0x3fffffff);
48 TrainingData::TrainingDataDictionary TrainingData::_archived_training_data_dictionary;
49 TrainingData::TrainingDataDictionary TrainingData::_archived_training_data_dictionary_for_dumping;
50 TrainingData::DumptimeTrainingDataDictionary* TrainingData::_dumptime_training_data_dictionary = nullptr;
51 int TrainingData::TrainingDataLocker::_lock_mode;
52 volatile bool TrainingData::TrainingDataLocker::_snapshot = false;
53
54 MethodTrainingData::MethodTrainingData() {
55 // Used by cppVtables.cpp only
56 assert(CDSConfig::is_dumping_static_archive() || UseSharedSpaces, "only for CDS");
57 }
58
59 KlassTrainingData::KlassTrainingData() {
60 // Used by cppVtables.cpp only
61 assert(CDSConfig::is_dumping_static_archive() || UseSharedSpaces, "only for CDS");
62 }
63
64 CompileTrainingData::CompileTrainingData() : _level(-1), _compile_id(-1) {
65 // Used by cppVtables.cpp only
66 assert(CDSConfig::is_dumping_static_archive() || UseSharedSpaces, "only for CDS");
67 }
68
69 void TrainingData::initialize() {
70 // this is a nop if training modes are not enabled
71 if (have_data() || need_data()) {
72 // Data structures that we have do not currently support iterative training. So you cannot replay
73 // and train at the same time. Going forward we may want to adjust iteration/search to enable that.
74 guarantee(have_data() != need_data(), "Iterative training is not supported");
75 TrainingDataLocker::initialize();
76 }
77 RecompilationSchedule::initialize();
78 }
79
80 static void verify_archived_entry(TrainingData* td, const TrainingData::Key* k) {
81 guarantee(TrainingData::Key::can_compute_cds_hash(k), "");
82 TrainingData* td1 = TrainingData::lookup_archived_training_data(k);
83 guarantee(td == td1, "");
84 }
85
86 void TrainingData::verify() {
87 if (TrainingData::have_data() && !TrainingData::assembling_data()) {
88 archived_training_data_dictionary()->iterate([&](TrainingData* td) {
89 if (td->is_KlassTrainingData()) {
90 KlassTrainingData* ktd = td->as_KlassTrainingData();
91 if (ktd->has_holder() && ktd->holder()->is_loaded()) {
92 Key k(ktd->holder());
93 verify_archived_entry(td, &k);
94 }
95 ktd->verify();
96 } else if (td->is_MethodTrainingData()) {
97 MethodTrainingData* mtd = td->as_MethodTrainingData();
474 _dumptime_training_data_dictionary = new DumptimeTrainingDataDictionary();
475 _archived_training_data_dictionary.iterate([&](TrainingData* record) {
476 _dumptime_training_data_dictionary->append(record);
477 });
478 }
479 if (need_data()) {
480 _dumptime_training_data_dictionary = new DumptimeTrainingDataDictionary();
481 TrainingDataLocker l;
482 TrainingDataLocker::snapshot();
483
484 ResourceMark rm;
485 Visitor visitor(training_data_set()->size());
486 training_data_set()->iterate([&](TrainingData* td) {
487 td->prepare(visitor);
488 if (!td->is_CompileTrainingData()) {
489 _dumptime_training_data_dictionary->append(td);
490 }
491 });
492 }
493
494 RecompilationSchedule::prepare(CHECK);
495
496 if (AOTVerifyTrainingData) {
497 TrainingData::verify();
498 }
499 }
500
501 void TrainingData::iterate_roots(MetaspaceClosure* it) {
502 if (_dumptime_training_data_dictionary != nullptr) {
503 for (int i = 0; i < _dumptime_training_data_dictionary->length(); i++) {
504 _dumptime_training_data_dictionary->at(i).metaspace_pointers_do(it);
505 }
506 }
507 RecompilationSchedule::iterate_roots(it);
508 }
509
510 void TrainingData::dump_training_data() {
511 if (_dumptime_training_data_dictionary != nullptr) {
512 CompactHashtableStats stats;
513 _archived_training_data_dictionary_for_dumping.reset();
514 CompactHashtableWriter writer(_dumptime_training_data_dictionary->length(), &stats);
515 for (int i = 0; i < _dumptime_training_data_dictionary->length(); i++) {
516 TrainingData* td = _dumptime_training_data_dictionary->at(i).training_data();
517 #ifdef ASSERT
518 for (int j = i+1; j < _dumptime_training_data_dictionary->length(); j++) {
519 TrainingData* td1 = _dumptime_training_data_dictionary->at(j).training_data();
520 assert(!TrainingData::Key::equals(td1, td->key(), -1), "conflict");
521 }
522 #endif // ASSERT
523 td = ArchiveBuilder::current()->get_buffered_addr(td);
524 uint hash = TrainingData::Key::cds_hash(td->key());
525 u4 delta = ArchiveBuilder::current()->buffer_to_offset_u4((address)td);
526 writer.add(hash, delta);
527 }
534 ResourceMark rm;
535 Visitor visitor(_dumptime_training_data_dictionary->length());
536 for (int i = 0; i < _dumptime_training_data_dictionary->length(); i++) {
537 TrainingData* td = _dumptime_training_data_dictionary->at(i).training_data();
538 td->cleanup(visitor);
539 }
540 // Throw away all elements with empty keys
541 int j = 0;
542 for (int i = 0; i < _dumptime_training_data_dictionary->length(); i++) {
543 TrainingData* td = _dumptime_training_data_dictionary->at(i).training_data();
544 if (td->key()->is_empty()) {
545 continue;
546 }
547 if (i != j) { // no need to copy if it's the same
548 _dumptime_training_data_dictionary->at_put(j, td);
549 }
550 j++;
551 }
552 _dumptime_training_data_dictionary->trunc_to(j);
553 }
554 RecompilationSchedule::cleanup();
555 }
556
557 void KlassTrainingData::cleanup(Visitor& visitor) {
558 if (visitor.is_visited(this)) {
559 return;
560 }
561 visitor.visit(this);
562 if (has_holder()) {
563 bool is_excluded = !holder()->is_loaded() || SystemDictionaryShared::check_for_exclusion(holder(), nullptr);
564 if (is_excluded) {
565 ResourceMark rm;
566 log_debug(aot, training)("Cleanup KTD %s", name()->as_klass_external_name());
567 _holder = nullptr;
568 key()->make_empty();
569 }
570 }
571 for (int i = 0; i < _comp_deps.length(); i++) {
572 _comp_deps.at(i)->cleanup(visitor);
573 }
574 }
643 tty->cr();
644 }
645 guarantee(invariant, "init deps invariant violation: %d >= %d", init_deps_left1, init_deps_left2);
646 }
647 }
648
649 void CompileTrainingData::cleanup(Visitor& visitor) {
650 if (visitor.is_visited(this)) {
651 return;
652 }
653 visitor.visit(this);
654 method()->cleanup(visitor);
655 }
656
657 void TrainingData::serialize(SerializeClosure* soc) {
658 if (soc->writing()) {
659 _archived_training_data_dictionary_for_dumping.serialize_header(soc);
660 } else {
661 _archived_training_data_dictionary.serialize_header(soc);
662 }
663 RecompilationSchedule::serialize(soc);
664 }
665
666 class TrainingDataPrinter : StackObj {
667 outputStream* _st;
668 int _index;
669 public:
670 TrainingDataPrinter(outputStream* st) : _st(st), _index(0) {}
671 void do_value(TrainingData* td) {
672 const char* type = (td->is_KlassTrainingData() ? "K" :
673 td->is_MethodTrainingData() ? "M" :
674 td->is_CompileTrainingData() ? "C" : "?");
675 _st->print("%4d: %p %s ", _index++, td, type);
676 td->print_on(_st);
677 _st->cr();
678 if (td->is_KlassTrainingData()) {
679 td->as_KlassTrainingData()->iterate_comp_deps([&](CompileTrainingData* ctd) {
680 ResourceMark rm;
681 _st->print_raw(" C ");
682 ctd->print_on(_st);
683 _st->cr();
684 });
685 } else if (td->is_MethodTrainingData()) {
686 td->as_MethodTrainingData()->iterate_compiles([&](CompileTrainingData* ctd) {
687 ResourceMark rm;
688 _st->print_raw(" C ");
689 ctd->print_on(_st);
690 _st->cr();
691 });
692 } else if (td->is_CompileTrainingData()) {
693 // ?
694 }
695 }
696 };
697
698 void TrainingData::print_archived_training_data_on(outputStream* st) {
699 st->print_cr("Archived TrainingData Dictionary");
700 TrainingDataPrinter tdp(st);
701 TrainingDataLocker::initialize();
702 _archived_training_data_dictionary.iterate(&tdp);
703 RecompilationSchedule::print_archived_training_data_on(st);
704 }
705
706 void TrainingData::Key::metaspace_pointers_do(MetaspaceClosure *iter) {
707 iter->push(const_cast<Metadata**>(&_meta));
708 }
709
710 void TrainingData::metaspace_pointers_do(MetaspaceClosure* iter) {
711 _key.metaspace_pointers_do(iter);
712 }
713
714 bool TrainingData::Key::can_compute_cds_hash(const Key* const& k) {
715 return k->meta() == nullptr || MetaspaceObj::in_aot_cache(k->meta());
716 }
717
718 uint TrainingData::Key::cds_hash(const Key* const& k) {
719 return SystemDictionaryShared::hash_for_shared_dictionary((address)k->meta());
720 }
721
722 TrainingData* TrainingData::lookup_archived_training_data(const Key* k) {
723 // For this to work, all components of the key must be in shared metaspace.
|