< prev index next >

src/hotspot/share/oops/trainingData.cpp

Print this page

 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.
< prev index next >