1 /*
  2  * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  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
  7  * published by the Free Software Foundation.
  8  *
  9  * This code is distributed in the hope that it will be useful, but WITHOUT
 10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12  * version 2 for more details (a copy is included in the LICENSE file that
 13  * accompanied this code).
 14  *
 15  * You should have received a copy of the GNU General Public License version
 16  * 2 along with this work; if not, write to the Free Software Foundation,
 17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18  *
 19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20  * or visit www.oracle.com if you need additional information or have any
 21  * questions.
 22  *
 23  */
 24 
 25 #include "cds/methodProfiler.hpp"
 26 #include "code/nmethod.hpp"
 27 #include "memory/metadataFactory.hpp"
 28 #include "oops/recompilationSchedule.hpp"
 29 #include "oops/trainingData.hpp"
 30 
 31 Array<MethodTrainingData*>* RecompilationSchedule::_schedule = nullptr;
 32 Array<MethodTrainingData*>* RecompilationSchedule::_schedule_for_dumping = nullptr;
 33 volatile bool* RecompilationSchedule::_status = nullptr;
 34 
 35 void RecompilationSchedule::initialize() {
 36   if (TrainingData::have_data()) {
 37     if (_schedule != nullptr && _schedule->length() > 0) {
 38       const int size = _schedule->length();
 39       _status = NEW_C_HEAP_ARRAY(bool, size, mtCompiler);
 40       for (int i = 0; i < size; i++) {
 41         _status[i] = false;
 42       }
 43     }
 44   }
 45 }
 46 
 47 void RecompilationSchedule::prepare(TRAPS) {
 48   if (TrainingData::assembling_data() && _schedule != nullptr) {
 49     ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data();
 50     _schedule_for_dumping = MetadataFactory::new_array<MethodTrainingData*>(loader_data, _schedule->length(), CHECK);
 51     for (int i = 0; i < _schedule->length(); i++) {
 52       _schedule_for_dumping->at_put(i, _schedule->at(i));
 53     }
 54   }
 55   if (TrainingData::need_data()) {
 56 #if INCLUDE_CDS
 57     auto nmethods = MethodProfiler::sampled_nmethods();
 58     GrowableArray<MethodTrainingData*> dyn_schedule;
 59     for (auto it = nmethods->begin(); it != nmethods->end(); ++it) {
 60       nmethod* nm = *it;
 61       if (AOTRecordOnlyTopCompilations && nm->method_profiling_count() == 0) {
 62         break;
 63       }
 64       if (nm->method() != nullptr) {
 65         MethodTrainingData* mtd = nm->method()->training_data_or_null();
 66         if (mtd != nullptr) {
 67           dyn_schedule.append(mtd);
 68         }
 69       }
 70     }
 71     delete nmethods;
 72     ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data();
 73     _schedule_for_dumping = MetadataFactory::new_array<MethodTrainingData*>(loader_data, dyn_schedule.length(), CHECK);
 74     int i = 0;
 75     for (auto it = dyn_schedule.begin(); it != dyn_schedule.end(); ++it) {
 76       _schedule_for_dumping->at_put(i++, *it);
 77     }
 78 #endif
 79   }
 80 }
 81 
 82 #if INCLUDE_CDS
 83 void RecompilationSchedule::iterate_roots(MetaspaceClosure* it) {
 84   if (_schedule_for_dumping != nullptr) {
 85     it->push(&_schedule_for_dumping);
 86   }
 87 }
 88 
 89 void RecompilationSchedule::cleanup() {
 90   _status = nullptr;
 91 }
 92 
 93 void RecompilationSchedule::serialize(SerializeClosure* soc) {
 94   if (soc->writing()) {
 95     soc->do_ptr(&_schedule_for_dumping);
 96   } else {
 97     soc->do_ptr(&_schedule);
 98   }
 99 }
100 
101 
102 void RecompilationSchedule::print_archived_training_data_on(outputStream* st) {
103   if (_schedule != nullptr && _schedule->length() > 0) {
104     st->print_cr("Archived TrainingData Recompilation Schedule");
105     for (int i = 0; i < _schedule->length(); i++) {
106       st->print("%4d: ", i);
107       MethodTrainingData* mtd = _schedule->at(i);
108       if (mtd != nullptr) {
109         mtd->print_on(st);
110       } else {
111         st->print("nullptr");
112       }
113       st->cr();
114     }
115   }
116 }
117 #endif //INCLUDE_CDS