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