2
* Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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.
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).
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.
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
24
#include "precompiled.hpp"
25
#include "classfile/vmClasses.hpp"
26
#include "compiler/compileBroker.hpp"
27
#include "compiler/compilerDefinitions.inline.hpp"
28
#include "classfile/moduleEntry.hpp"
29
#include "classfile/vmSymbols.hpp"
30
#include "jvmci/jvmciEnv.hpp"
31
#include "jvmci/jvmciRuntime.hpp"
32
#include "oops/objArrayOop.inline.hpp"
33
#include "runtime/arguments.hpp"
34
#include "runtime/handles.inline.hpp"
36
JVMCICompiler* JVMCICompiler::_instance = nullptr;
38
JVMCICompiler::JVMCICompiler() : AbstractCompiler(compiler_jvmci) {
39
_bootstrapping = false;
40
_bootstrap_compilation_request_handled = false;
41
_methods_compiled = 0;
45
_global_compilation_ticks = 0;
46
assert(_instance == nullptr, "only one instance allowed");
50
JVMCICompiler* JVMCICompiler::instance(bool require_non_null, TRAPS) {
52
THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), "JVMCI is not enabled")
54
if (_instance == nullptr && require_non_null) {
55
THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), "The JVMCI compiler instance has not been created");
60
void compiler_stubs_init(bool in_compiler_thread);
63
void JVMCICompiler::initialize() {
64
assert(!CompilerConfig::is_c1_or_interpreter_only_no_jvmci(), "JVMCI is launched, it's not c1/interpreter only mode");
65
if (!UseCompiler || !EnableJVMCI || !UseJVMCICompiler || !should_perform_init()) {
68
compiler_stubs_init(true /* in_compiler_thread */); // generate compiler's intrinsics stubs
69
set_state(initialized);
72
void JVMCICompiler::bootstrap(TRAPS) {
73
if (Arguments::mode() == Arguments::_int) {
74
// Nothing to do in -Xint mode
77
_bootstrapping = true;
78
ResourceMark rm(THREAD);
79
HandleMark hm(THREAD);
81
tty->print("Bootstrapping JVMCI");
83
jlong start = os::javaTimeNanos();
85
Array<Method*>* objectMethods = vmClasses::Object_klass()->methods();
86
// Initialize compile queue with a selected set of methods.
87
int len = objectMethods->length();
88
for (int i = 0; i < len; i++) {
89
methodHandle mh(THREAD, objectMethods->at(i));
90
if (!mh->is_native() && !mh->is_static() && !mh->is_initializer()) {
92
int hot_count = 10; // TODO: what's the appropriate value?
93
CompileBroker::compile_method(mh, InvocationEntryBci, CompLevel_full_optimization, mh, hot_count, CompileTask::Reason_Bootstrap, CHECK);
98
bool first_round = true;
101
// Loop until there is something in the queue.
104
qsize = CompileBroker::queue_size(CompLevel_full_optimization);
105
} while (!_bootstrap_compilation_request_handled && first_round && qsize == 0);
107
if (PrintBootstrap) {
108
while (z < (_methods_compiled / 100)) {
113
} while (qsize != 0);
115
if (PrintBootstrap) {
116
tty->print_cr(" in " JLONG_FORMAT " ms (compiled %d methods)",
117
(jlong)nanos_to_millis(os::javaTimeNanos() - start), _methods_compiled);
119
_bootstrapping = false;
120
JVMCI::java_runtime()->bootstrap_finished(CHECK);
123
bool JVMCICompiler::force_comp_at_level_simple(const methodHandle& method) {
127
if (_bootstrapping) {
128
// When bootstrapping, the JVMCI compiler can compile its own methods.
131
if (UseJVMCINativeLibrary) {
132
// This mechanism exists to force compilation of a JVMCI compiler by C1
133
// to reduce the compilation time spent on the JVMCI compiler itself. In
134
// +UseJVMCINativeLibrary mode, the JVMCI compiler is AOT compiled.
137
JVMCIRuntime* runtime = JVMCI::java_runtime();
138
if (runtime != nullptr) {
139
JVMCIObject receiver = runtime->probe_HotSpotJVMCIRuntime();
140
if (receiver.is_null()) {
143
JVMCIEnv* ignored_env = nullptr;
144
objArrayHandle excludeModules(JavaThread::current(), HotSpotJVMCI::HotSpotJVMCIRuntime::excludeFromJVMCICompilation(ignored_env, HotSpotJVMCI::resolve(receiver)));
145
if (excludeModules.not_null()) {
146
ModuleEntry* moduleEntry = method->method_holder()->module();
147
for (int i = 0; i < excludeModules->length(); i++) {
148
if (excludeModules->obj_at(i) == moduleEntry->module()) {
158
// Compilation entry point for methods
159
void JVMCICompiler::compile_method(ciEnv* env, ciMethod* target, int entry_bci, bool install_code, DirectiveSet* directive) {
160
ShouldNotReachHere();
163
void JVMCICompiler::stopping_compiler_thread(CompilerThread* current) {
164
if (UseJVMCINativeLibrary) {
165
JVMCIRuntime* runtime = JVMCI::compiler_runtime(current, false);
166
if (runtime != nullptr) {
167
MutexUnlocker unlock(CompileThread_lock);
168
runtime->detach_thread(current, "stopping idle compiler thread");
173
void JVMCICompiler::on_empty_queue(CompileQueue* queue, CompilerThread* thread) {
174
if (UseJVMCINativeLibrary) {
175
int delay = JVMCICompilerIdleDelay;
176
JVMCIRuntime* runtime = JVMCI::compiler_runtime(thread, false);
177
// Don't detach JVMCI compiler threads from their JVMCI
178
// runtime during the VM startup grace period
179
if (runtime != nullptr && delay > 0 && tty->time_stamp().milliseconds() > DEFAULT_COMPILER_IDLE_DELAY) {
180
bool timeout = MethodCompileQueue_lock->wait(delay);
181
// Unlock as detaching or repacking can result in a JNI call to shutdown a JavaVM
182
// and locks cannot be held when making a VM to native transition.
183
MutexUnlocker unlock(MethodCompileQueue_lock);
185
runtime->detach_thread(thread, "releasing idle compiler thread");
187
runtime->repack(thread);
193
// Print compilation timers
194
void JVMCICompiler::print_timers() {
195
tty->print_cr(" JVMCI CompileBroker Time:");
196
tty->print_cr(" Compile: %7.3f s", stats()->total_time());
197
_jit_code_installs.print_on(tty, " Install Code: ");
199
tty->print_cr(" JVMCI Hosted Time:");
200
_hosted_code_installs.print_on(tty, " Install Code: ");
203
bool JVMCICompiler::is_intrinsic_supported(const methodHandle& method) {
204
vmIntrinsics::ID id = method->intrinsic_id();
205
assert(id != vmIntrinsics::_none, "must be a VM intrinsic");
206
JavaThread* thread = JavaThread::current();
207
JVMCIEnv jvmciEnv(thread, __FILE__, __LINE__);
208
JVMCIRuntime* runtime = JVMCI::compiler_runtime(thread, false);
209
return runtime->is_intrinsic_supported(&jvmciEnv, (jint) id);
212
void JVMCICompiler::CodeInstallStats::print_on(outputStream* st, const char* prefix) const {
213
double time = _timer.seconds();
214
st->print_cr("%s%7.3f s (installs: %d, CodeBlob total size: %d, CodeBlob code size: %d)",
215
prefix, time, _count, _codeBlobs_size, _codeBlobs_code_size);
218
void JVMCICompiler::CodeInstallStats::on_install(CodeBlob* cb) {
219
Atomic::inc(&_count);
220
Atomic::add(&_codeBlobs_size, cb->size());
221
Atomic::add(&_codeBlobs_code_size, cb->code_size());
224
void JVMCICompiler::inc_methods_compiled() {
225
Atomic::inc(&_methods_compiled);
226
Atomic::inc(&_global_compilation_ticks);
229
void JVMCICompiler::on_upcall(const char* error, JVMCICompileState* compile_state) {
230
if (error != nullptr) {
232
Atomic::inc(&_err_upcalls);
233
int ok = _ok_upcalls;
234
int err = _err_upcalls;
235
// If there have been at least 10 upcalls with an error
236
// and the number of error upcalls is 10% or more of the
237
// number of non-error upcalls, disable JVMCI compilation.
238
if (err > 10 && err * 10 > ok && !_disabled) {
240
int total = err + ok;
241
// Using stringStream instead of err_msg to avoid truncation
243
st.print("JVMCI compiler disabled "
244
"after %d of %d upcalls had errors (Last error: \"%s\"). "
245
"Use -Xlog:jit+compilation for more detail.", err, total, error);
246
const char* disable_msg = st.freeze();
247
log_warning(jit,compilation)("%s", disable_msg);
248
if (compile_state != nullptr) {
249
const char* disable_error = os::strdup(disable_msg);
250
if (disable_error != nullptr) {
251
compile_state->set_failure(true, disable_error, true);
252
JVMCI_event_1("%s", disable_error);
255
// Leave failure reason as set by caller when strdup fails
259
JVMCI_event_1("JVMCI upcall had an error: %s", error);
261
Atomic::inc(&_ok_upcalls);
265
void JVMCICompiler::inc_global_compilation_ticks() {
266
Atomic::inc(&_global_compilation_ticks);