jdk

Форк
0
/
jvmciCompiler.cpp 
267 строк · 9.6 Кб
1
/*
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.
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
#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"
35

36
JVMCICompiler* JVMCICompiler::_instance = nullptr;
37

38
JVMCICompiler::JVMCICompiler() : AbstractCompiler(compiler_jvmci) {
39
  _bootstrapping = false;
40
  _bootstrap_compilation_request_handled = false;
41
  _methods_compiled = 0;
42
  _ok_upcalls = 0;
43
  _err_upcalls = 0;
44
  _disabled = false;
45
  _global_compilation_ticks = 0;
46
  assert(_instance == nullptr, "only one instance allowed");
47
  _instance = this;
48
}
49

50
JVMCICompiler* JVMCICompiler::instance(bool require_non_null, TRAPS) {
51
  if (!EnableJVMCI) {
52
    THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), "JVMCI is not enabled")
53
  }
54
  if (_instance == nullptr && require_non_null) {
55
    THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), "The JVMCI compiler instance has not been created");
56
  }
57
  return _instance;
58
}
59

60
void compiler_stubs_init(bool in_compiler_thread);
61

62
// Initialization
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()) {
66
    return;
67
  }
68
  compiler_stubs_init(true /* in_compiler_thread */); // generate compiler's intrinsics stubs
69
  set_state(initialized);
70
}
71

72
void JVMCICompiler::bootstrap(TRAPS) {
73
  if (Arguments::mode() == Arguments::_int) {
74
    // Nothing to do in -Xint mode
75
    return;
76
  }
77
  _bootstrapping = true;
78
  ResourceMark rm(THREAD);
79
  HandleMark hm(THREAD);
80
  if (PrintBootstrap) {
81
    tty->print("Bootstrapping JVMCI");
82
  }
83
  jlong start = os::javaTimeNanos();
84

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()) {
91
      ResourceMark rm;
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);
94
    }
95
  }
96

97
  int qsize;
98
  bool first_round = true;
99
  int z = 0;
100
  do {
101
    // Loop until there is something in the queue.
102
    do {
103
      THREAD->sleep(100);
104
      qsize = CompileBroker::queue_size(CompLevel_full_optimization);
105
    } while (!_bootstrap_compilation_request_handled && first_round && qsize == 0);
106
    first_round = false;
107
    if (PrintBootstrap) {
108
      while (z < (_methods_compiled / 100)) {
109
        ++z;
110
        tty->print_raw(".");
111
      }
112
    }
113
  } while (qsize != 0);
114

115
  if (PrintBootstrap) {
116
    tty->print_cr(" in " JLONG_FORMAT " ms (compiled %d methods)",
117
                  (jlong)nanos_to_millis(os::javaTimeNanos() - start), _methods_compiled);
118
  }
119
  _bootstrapping = false;
120
  JVMCI::java_runtime()->bootstrap_finished(CHECK);
121
}
122

123
bool JVMCICompiler::force_comp_at_level_simple(const methodHandle& method) {
124
  if (_disabled) {
125
    return true;
126
  }
127
  if (_bootstrapping) {
128
    // When bootstrapping, the JVMCI compiler can compile its own methods.
129
    return false;
130
  }
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.
135
    return false;
136
  } else {
137
    JVMCIRuntime* runtime = JVMCI::java_runtime();
138
    if (runtime != nullptr) {
139
      JVMCIObject receiver = runtime->probe_HotSpotJVMCIRuntime();
140
      if (receiver.is_null()) {
141
        return false;
142
      }
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()) {
149
            return true;
150
          }
151
        }
152
      }
153
    }
154
    return false;
155
  }
156
}
157

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();
161
}
162

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");
169
    }
170
  }
171
}
172

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);
184
      if (timeout) {
185
        runtime->detach_thread(thread, "releasing idle compiler thread");
186
      } else {
187
        runtime->repack(thread);
188
      }
189
    }
190
  }
191
}
192

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:   ");
198
  tty->cr();
199
  tty->print_cr("    JVMCI Hosted Time:");
200
  _hosted_code_installs.print_on(tty, "       Install Code:   ");
201
}
202

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);
210
}
211

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);
216
}
217

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());
222
}
223

224
void JVMCICompiler::inc_methods_compiled() {
225
  Atomic::inc(&_methods_compiled);
226
  Atomic::inc(&_global_compilation_ticks);
227
}
228

229
void JVMCICompiler::on_upcall(const char* error, JVMCICompileState* compile_state) {
230
  if (error != nullptr) {
231

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) {
239
      _disabled = true;
240
      int total = err + ok;
241
      // Using stringStream instead of err_msg to avoid truncation
242
      stringStream st;
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);
253
          return;
254
        } else {
255
          // Leave failure reason as set by caller when strdup fails
256
        }
257
      }
258
    }
259
    JVMCI_event_1("JVMCI upcall had an error: %s", error);
260
  } else {
261
    Atomic::inc(&_ok_upcalls);
262
  }
263
}
264

265
void JVMCICompiler::inc_global_compilation_ticks() {
266
  Atomic::inc(&_global_compilation_ticks);
267
}
268

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.