1 /*
  2  * Copyright (c) 2023, 2025, 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/aotCacheAccess.hpp"
 26 #include "cds/archiveBuilder.hpp"
 27 #include "cds/cdsConfig.hpp"
 28 #include "cds/runTimeClassInfo.hpp"
 29 #include "code/aotCodeCache.hpp"
 30 #include "compiler/compilationPolicy.hpp"
 31 #include "compiler/compileBroker.hpp"
 32 #include "compiler/compiler_globals.hpp"
 33 #include "compiler/precompiler.hpp"
 34 #include "logging/logStream.hpp"
 35 #include "memory/allocation.hpp"
 36 #include "oops/trainingData.hpp"
 37 #include "runtime/handles.inline.hpp"
 38 
 39 class PrecompileIterator : StackObj {
 40 private:
 41   CompLevel _comp_level;
 42   CompLevel _search_level;
 43   bool _for_preload;
 44   Thread* _thread;
 45   GrowableArray<Method*> _methods;
 46 
 47 public:
 48   PrecompileIterator(CompLevel comp_level, bool for_preload, CompLevel search_level, JavaThread* thread)
 49   : _comp_level(comp_level), _search_level(search_level), _for_preload(for_preload), _thread(thread) {
 50     assert(TrainingData::have_data(), "sanity");
 51   }
 52 
 53   bool include(Method* m) {
 54     if (m->is_native() || m->is_abstract()) {
 55       return false;
 56     }
 57     DirectiveSet* directives = DirectivesStack::getMatchingDirective(methodHandle(_thread, m), nullptr);
 58     if (directives->DontPrecompileOption) {
 59       return false; // excluded
 60     } else if (directives->PrecompileRecordedOption > 0) {
 61       return true;
 62     }
 63     int cid = compile_id(m, _search_level);
 64     return (cid < INT_MAX);
 65   }
 66 
 67   void do_value(const RunTimeClassInfo* record) {
 68     Array<Method*>* methods = record->klass()->methods();
 69     for (int i = 0; i < methods->length(); i++) {
 70       Method* m = methods->at(i);
 71       if (include(m)) {
 72         _methods.push(m);
 73       }
 74     }
 75   }
 76   void operator()(TrainingData* td) {
 77     if (td->is_MethodTrainingData()) {
 78       MethodTrainingData* mtd = td->as_MethodTrainingData();
 79       if (mtd->has_holder() && include((Method*)mtd->holder())) {
 80         _methods.push((Method*)mtd->holder());
 81       }
 82     }
 83   }
 84 
 85   static int compile_id(Method* m, int level) {
 86     MethodTrainingData* mtd = m->method_holder()->is_loaded() ? MethodTrainingData::find(methodHandle(Thread::current(), m)) : nullptr;
 87     if (mtd != nullptr && mtd->highest_level() == level) {
 88       CompileTrainingData* ctd = mtd->last_toplevel_compile(level);
 89       if (ctd != nullptr) {
 90         return ctd->compile_id();
 91       }
 92     }
 93     return INT_MAX; // treat as the last compilation
 94   }
 95 
 96   static int compare_by_compile_id(Method** m1, Method** m2, CompLevel comp_level) {
 97     int id1 = compile_id(*m1, comp_level);
 98     int id2 = compile_id(*m2, comp_level);
 99     return (id1 - id2);
100   }
101 
102   static int compare_by_compile_id_tier1(Method** m1, Method** m2) {
103     return compare_by_compile_id(m1, m2, CompLevel_simple);
104   }
105 
106   static int compare_by_compile_id_tier2(Method** m1, Method** m2) {
107     return compare_by_compile_id(m1, m2, CompLevel_limited_profile);
108   }
109 
110   static int compare_by_compile_id_tier3(Method** m1, Method** m2) {
111     return compare_by_compile_id(m1, m2, CompLevel_full_profile);
112   }
113 
114   static int compare_by_compile_id_tier4(Method** m1, Method** m2) {
115     return compare_by_compile_id(m1, m2, CompLevel_full_optimization);
116   }
117 
118   void sort_methods_by_compile_id() {
119     switch(_search_level) {
120       case CompLevel_simple:            _methods.sort(&compare_by_compile_id_tier1); break;
121       case CompLevel_limited_profile:   _methods.sort(&compare_by_compile_id_tier2); break;
122       case CompLevel_full_profile:      _methods.sort(&compare_by_compile_id_tier3); break;
123       case CompLevel_full_optimization: _methods.sort(&compare_by_compile_id_tier4); break;
124 
125       default: fatal("%d", _search_level);
126     }
127   }
128 
129   void schedule_compilations(TRAPS) {
130     for (int i = 0; i < _methods.length(); i++) {
131       Method* m = _methods.at(i);
132       methodHandle mh(THREAD, m);
133       assert(mh()->method_holder()->is_linked(), "required");
134       if (!AOTCacheAccess::can_generate_aot_code(m)) {
135         continue; // Method is not archived
136       }
137       assert(!HAS_PENDING_EXCEPTION, "");
138       CompileBroker::compile_method(mh, InvocationEntryBci, _comp_level,
139                                     0,
140                                     true /*requires_online_comp*/,
141                                     _for_preload ? CompileTask::Reason_PrecompileForPreload : CompileTask::Reason_Precompile,
142                                     THREAD);
143       if (HAS_PENDING_EXCEPTION) {
144         CLEAR_PENDING_EXCEPTION;
145       }
146     }
147   }
148 
149   void print_compilation_status(ArchiveBuilder* builder) {
150     int success_count = 0;
151     const int log_comp_level = _comp_level + (_for_preload ? 1 : 0);
152 
153     for (int i = 0; i < _methods.length(); i++) {
154       Method* m = _methods.at(i);
155 
156       bool is_success = !m->is_not_compilable(_comp_level);
157       if (is_success) {
158         success_count++;
159       }
160 
161       LogStreamHandle(Info, precompile) log;
162       if (log.is_enabled()) {
163         ResourceMark rm;
164         log.print("[%4d] T%d Compiled %s [%p", i, log_comp_level, m->external_name(), m);
165         if (builder != nullptr) {
166           Method* requested_m = builder->to_requested(builder->get_buffered_addr(m));
167           log.print(" -> %p", requested_m);
168         }
169         log.print("] [%d] (%s)", AOTCodeCache::store_entries_cnt(), (is_success ? "success" : "FAILED"));
170       }
171     }
172 
173     log_info(precompile)("Precompilation for level %d finished (%d successful out of %d total)",
174       log_comp_level, success_count, _methods.length());
175   }
176 
177   void precompile(ArchiveBuilder* builder, TRAPS) {
178     sort_methods_by_compile_id();
179     schedule_compilations(THREAD);
180     CompileBroker::wait_for_no_active_tasks();
181     print_compilation_status(builder);
182   }
183 };
184 
185 void Precompiler::compile_aot_code(CompLevel search_level, bool for_preload, CompLevel comp_level, TRAPS) {
186   ResourceMark rm;
187   PrecompileIterator pi(comp_level, for_preload, search_level, THREAD);
188   TrainingData::iterate(pi);
189   pi.precompile((ArchiveBuilder*)nullptr, THREAD);
190 }
191 
192 void Precompiler::compile_aot_code(TRAPS) {
193   if (!AOTCodeCache::is_dumping_code()) {
194     return;
195   }
196   log_info(precompile)("Precompilation started");
197   if (TrainingData::have_data()) {
198     TrainingData::iterate([&](TrainingData* td) {
199       if (td->is_KlassTrainingData()) {
200         KlassTrainingData *ktd = td->as_KlassTrainingData();
201         if (ktd->has_holder()) {
202           assert(!HAS_PENDING_EXCEPTION, "");
203           ktd->holder()->link_class(THREAD);
204           if (HAS_PENDING_EXCEPTION) {
205             LogStreamHandle(Warning, precompile) log;
206             if (log.is_enabled()) {
207               ResourceMark rm;
208               log.print("Linkage failed for %s: ", ktd->holder()->external_name());
209               PENDING_EXCEPTION->print_on(&log);
210             }
211             CLEAR_PENDING_EXCEPTION;
212           }
213         }
214       }
215     });
216 
217     if (ClassInitBarrierMode > 0) { // Preload code is enabled
218       compile_aot_code(CompLevel_full_optimization, true, CompLevel_full_optimization, CHECK);
219     }
220     compile_aot_code(CompLevel_full_optimization, false, CompLevel_full_optimization, CHECK);
221     compile_aot_code(CompLevel_full_profile,      false, CompLevel_limited_profile,   CHECK);
222     compile_aot_code(CompLevel_limited_profile,   false, CompLevel_limited_profile,   CHECK);
223     compile_aot_code(CompLevel_simple,            false, CompLevel_simple,            CHECK);
224   }
225 }
226 
227 // New workflow only
228 void Precompiler::compile_aot_code(ArchiveBuilder* builder, TRAPS) {
229   assert(AOTCodeCache::is_dumping_code(), "sanity");
230   if (TrainingData::have_data()) {
231     ResourceMark rm;
232     CompLevel highest_level = CompilationPolicy::highest_compile_level();
233     if (highest_level >= CompLevel_full_optimization && ClassInitBarrierMode > 0) {
234       PrecompileIterator pi(CompLevel_full_optimization, true /*for_preload*/, CompLevel_full_optimization, THREAD);
235       TrainingData::iterate(pi);
236       pi.precompile(builder, THREAD);
237     }
238 
239     for (int level = CompLevel_simple; level <= highest_level; level++) {
240       CompLevel comp_level = (CompLevel)level;
241       if (comp_level == CompLevel_full_profile) {
242         comp_level = CompLevel_limited_profile;
243       }
244       PrecompileIterator pi(comp_level, false /*for_preload*/, (CompLevel)level, THREAD);
245       TrainingData::iterate(pi);
246       pi.precompile(builder, THREAD);
247     }
248   }
249 }