jdk

Форк
0
/
compileTask.cpp 
481 строка · 15.9 Кб
1
/*
2
 * Copyright (c) 1998, 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 "precompiled.hpp"
26
#include "compiler/compilationPolicy.hpp"
27
#include "compiler/compileTask.hpp"
28
#include "compiler/compileLog.hpp"
29
#include "compiler/compileBroker.hpp"
30
#include "compiler/compilerDirectives.hpp"
31
#include "logging/log.hpp"
32
#include "logging/logStream.hpp"
33
#include "memory/resourceArea.hpp"
34
#include "oops/klass.inline.hpp"
35
#include "runtime/handles.inline.hpp"
36
#include "runtime/jniHandles.hpp"
37
#include "runtime/mutexLocker.hpp"
38

39
CompileTask*  CompileTask::_task_free_list = nullptr;
40

41
/**
42
 * Allocate a CompileTask, from the free list if possible.
43
 */
44
CompileTask* CompileTask::allocate() {
45
  MutexLocker locker(CompileTaskAlloc_lock);
46
  CompileTask* task = nullptr;
47

48
  if (_task_free_list != nullptr) {
49
    task = _task_free_list;
50
    _task_free_list = task->next();
51
    task->set_next(nullptr);
52
  } else {
53
    task = new CompileTask();
54
    task->set_next(nullptr);
55
    task->set_is_free(true);
56
  }
57
  assert(task->is_free(), "Task must be free.");
58
  task->set_is_free(false);
59
  return task;
60
}
61

62
/**
63
* Add a task to the free list.
64
*/
65
void CompileTask::free(CompileTask* task) {
66
  MutexLocker locker(CompileTaskAlloc_lock);
67
  if (!task->is_free()) {
68
    assert(!task->lock()->is_locked(), "Should not be locked when freed");
69
    if ((task->_method_holder != nullptr && JNIHandles::is_weak_global_handle(task->_method_holder)) ||
70
        (task->_hot_method_holder != nullptr && JNIHandles::is_weak_global_handle(task->_hot_method_holder))) {
71
      JNIHandles::destroy_weak_global(task->_method_holder);
72
      JNIHandles::destroy_weak_global(task->_hot_method_holder);
73
    } else {
74
      JNIHandles::destroy_global(task->_method_holder);
75
      JNIHandles::destroy_global(task->_hot_method_holder);
76
    }
77
    if (task->_failure_reason_on_C_heap && task->_failure_reason != nullptr) {
78
      os::free((void*) task->_failure_reason);
79
    }
80
    task->_failure_reason = nullptr;
81
    task->_failure_reason_on_C_heap = false;
82

83
    task->set_is_free(true);
84
    task->set_next(_task_free_list);
85
    _task_free_list = task;
86
  }
87
}
88

89
void CompileTask::initialize(int compile_id,
90
                             const methodHandle& method,
91
                             int osr_bci,
92
                             int comp_level,
93
                             const methodHandle& hot_method,
94
                             int hot_count,
95
                             CompileTask::CompileReason compile_reason,
96
                             bool is_blocking) {
97
  assert(!_lock->is_locked(), "bad locking");
98

99
  Thread* thread = Thread::current();
100
  _compile_id = compile_id;
101
  _method = method();
102
  _method_holder = JNIHandles::make_weak_global(Handle(thread, method->method_holder()->klass_holder()));
103
  _osr_bci = osr_bci;
104
  _is_blocking = is_blocking;
105
  JVMCI_ONLY(_has_waiter = CompileBroker::compiler(comp_level)->is_jvmci();)
106
  JVMCI_ONLY(_blocking_jvmci_compile_state = nullptr;)
107
  _comp_level = comp_level;
108
  _num_inlined_bytecodes = 0;
109

110
  _is_complete = false;
111
  _is_success = false;
112

113
  _hot_method = nullptr;
114
  _hot_method_holder = nullptr;
115
  _hot_count = hot_count;
116
  _time_queued = os::elapsed_counter();
117
  _time_started = 0;
118
  _compile_reason = compile_reason;
119
  _nm_content_size = 0;
120
  AbstractCompiler* comp = compiler();
121
  _directive = DirectivesStack::getMatchingDirective(method, comp);
122
  _nm_insts_size = 0;
123
  _nm_total_size = 0;
124
  _failure_reason = nullptr;
125
  _failure_reason_on_C_heap = false;
126
  _arena_bytes = 0;
127

128
  if (LogCompilation) {
129
    if (hot_method.not_null()) {
130
      if (hot_method == method) {
131
        _hot_method = _method;
132
      } else {
133
        _hot_method = hot_method();
134
        // only add loader or mirror if different from _method_holder
135
        _hot_method_holder = JNIHandles::make_weak_global(Handle(thread, hot_method->method_holder()->klass_holder()));
136
      }
137
    }
138
  }
139

140
  _next = nullptr;
141
}
142

143
/**
144
 * Returns the compiler for this task.
145
 */
146
AbstractCompiler* CompileTask::compiler() const {
147
  return CompileBroker::compiler(_comp_level);
148
}
149

150
// Replace weak handles by strong handles to avoid unloading during compilation.
151
CompileTask* CompileTask::select_for_compilation() {
152
  if (is_unloaded()) {
153
    // Guard against concurrent class unloading
154
    return nullptr;
155
  }
156
  Thread* thread = Thread::current();
157
  assert(_method->method_holder()->is_loader_alive(), "should be alive");
158
  Handle method_holder(thread, _method->method_holder()->klass_holder());
159
  JNIHandles::destroy_weak_global(_method_holder);
160
  JNIHandles::destroy_weak_global(_hot_method_holder);
161
  _method_holder = JNIHandles::make_global(method_holder);
162
  if (_hot_method != nullptr) {
163
    _hot_method_holder = JNIHandles::make_global(Handle(thread, _hot_method->method_holder()->klass_holder()));
164
  }
165
  return this;
166
}
167

168
void CompileTask::mark_on_stack() {
169
  if (is_unloaded()) {
170
    return;
171
  }
172
  // Mark these methods as something redefine classes cannot remove.
173
  _method->set_on_stack(true);
174
  if (_hot_method != nullptr) {
175
    _hot_method->set_on_stack(true);
176
  }
177
}
178

179
bool CompileTask::is_unloaded() const {
180
  return _method_holder != nullptr && JNIHandles::is_weak_global_handle(_method_holder) && JNIHandles::is_weak_global_cleared(_method_holder);
181
}
182

183
// RedefineClasses support
184
void CompileTask::metadata_do(MetadataClosure* f) {
185
  if (is_unloaded()) {
186
    return;
187
  }
188
  f->do_metadata(method());
189
  if (hot_method() != nullptr && hot_method() != method()) {
190
    f->do_metadata(hot_method());
191
  }
192
}
193

194
// ------------------------------------------------------------------
195
// CompileTask::print_line_on_error
196
//
197
// This function is called by fatal error handler when the thread
198
// causing troubles is a compiler thread.
199
//
200
// Do not grab any lock, do not allocate memory.
201
//
202
// Otherwise it's the same as CompileTask::print_line()
203
//
204
void CompileTask::print_line_on_error(outputStream* st, char* buf, int buflen) {
205
  // print compiler name
206
  st->print("%s:", CompileBroker::compiler_name(comp_level()));
207
  print(st);
208
}
209

210
// ------------------------------------------------------------------
211
// CompileTask::print_tty
212
void CompileTask::print_tty() {
213
  ttyLocker ttyl;  // keep the following output all in one block
214
  print(tty);
215
}
216

217
// ------------------------------------------------------------------
218
// CompileTask::print_impl
219
void CompileTask::print_impl(outputStream* st, Method* method, int compile_id, int comp_level,
220
                             bool is_osr_method, int osr_bci, bool is_blocking,
221
                             const char* msg, bool short_form, bool cr,
222
                             jlong time_queued, jlong time_started) {
223
  if (!short_form) {
224
    // Print current time
225
    st->print(UINT64_FORMAT " ", (uint64_t) tty->time_stamp().milliseconds());
226
    if (Verbose && time_queued != 0) {
227
      // Print time in queue and time being processed by compiler thread
228
      jlong now = os::elapsed_counter();
229
      st->print("%.0f ", TimeHelper::counter_to_millis(now-time_queued));
230
      if (time_started != 0) {
231
        st->print("%.0f ", TimeHelper::counter_to_millis(now-time_started));
232
      }
233
    }
234
  }
235
  // print compiler name if requested
236
  if (CIPrintCompilerName) {
237
    st->print("%s:", CompileBroker::compiler_name(comp_level));
238
  }
239
  st->print("%4d ", compile_id);    // print compilation number
240

241
  bool is_synchronized = false;
242
  bool has_exception_handler = false;
243
  bool is_native = false;
244
  if (method != nullptr) {
245
    is_synchronized       = method->is_synchronized();
246
    has_exception_handler = method->has_exception_handler();
247
    is_native             = method->is_native();
248
  }
249
  // method attributes
250
  const char compile_type   = is_osr_method                   ? '%' : ' ';
251
  const char sync_char      = is_synchronized                 ? 's' : ' ';
252
  const char exception_char = has_exception_handler           ? '!' : ' ';
253
  const char blocking_char  = is_blocking                     ? 'b' : ' ';
254
  const char native_char    = is_native                       ? 'n' : ' ';
255

256
  // print method attributes
257
  st->print("%c%c%c%c%c ", compile_type, sync_char, exception_char, blocking_char, native_char);
258

259
  if (TieredCompilation) {
260
    if (comp_level != -1)  st->print("%d ", comp_level);
261
    else                   st->print("- ");
262
  }
263
  st->print("     ");  // more indent
264

265
  if (method == nullptr) {
266
    st->print("(method)");
267
  } else {
268
    method->print_short_name(st);
269
    if (is_osr_method) {
270
      st->print(" @ %d", osr_bci);
271
    }
272
    if (method->is_native())
273
      st->print(" (native)");
274
    else
275
      st->print(" (%d bytes)", method->code_size());
276
  }
277

278
  if (msg != nullptr) {
279
    st->print("   %s", msg);
280
  }
281
  if (cr) {
282
    st->cr();
283
  }
284
}
285

286
void CompileTask::print_inline_indent(int inline_level, outputStream* st) {
287
  //         1234567
288
  st->print("        ");     // print timestamp
289
  //         1234
290
  st->print("     ");        // print compilation number
291
  //         %s!bn
292
  st->print("      ");       // print method attributes
293
  if (TieredCompilation) {
294
    st->print("  ");
295
  }
296
  st->print("     ");        // more indent
297
  st->print("    ");         // initial inlining indent
298
  for (int i = 0; i < inline_level; i++)  st->print("  ");
299
}
300

301
// ------------------------------------------------------------------
302
// CompileTask::print_compilation
303
void CompileTask::print(outputStream* st, const char* msg, bool short_form, bool cr) {
304
  bool is_osr_method = osr_bci() != InvocationEntryBci;
305
  print_impl(st, is_unloaded() ? nullptr : method(), compile_id(), comp_level(), is_osr_method, osr_bci(), is_blocking(), msg, short_form, cr, _time_queued, _time_started);
306
}
307

308
// ------------------------------------------------------------------
309
// CompileTask::log_task
310
void CompileTask::log_task(xmlStream* log) {
311
  Thread* thread = Thread::current();
312
  methodHandle method(thread, this->method());
313
  ResourceMark rm(thread);
314

315
  // <task id='9' method='M' osr_bci='X' level='1' blocking='1' stamp='1.234'>
316
  log->print(" compile_id='%d'", _compile_id);
317
  if (_osr_bci != CompileBroker::standard_entry_bci) {
318
    log->print(" compile_kind='osr'");  // same as nmethod::compile_kind
319
  } // else compile_kind='c2c'
320
  if (!method.is_null())  log->method(method());
321
  if (_osr_bci != CompileBroker::standard_entry_bci) {
322
    log->print(" osr_bci='%d'", _osr_bci);
323
  }
324
  if (_comp_level != CompilationPolicy::highest_compile_level()) {
325
    log->print(" level='%d'", _comp_level);
326
  }
327
  if (_is_blocking) {
328
    log->print(" blocking='1'");
329
  }
330
  log->stamp();
331
}
332

333
// ------------------------------------------------------------------
334
// CompileTask::log_task_queued
335
void CompileTask::log_task_queued() {
336
  ttyLocker ttyl;
337
  ResourceMark rm;
338
  NoSafepointVerifier nsv;
339

340
  xtty->begin_elem("task_queued");
341
  log_task(xtty);
342
  assert(_compile_reason > CompileTask::Reason_None && _compile_reason < CompileTask::Reason_Count, "Valid values");
343
  xtty->print(" comment='%s'", reason_name(_compile_reason));
344

345
  if (_hot_method != nullptr && _hot_method != _method) {
346
    xtty->method(_hot_method);
347
  }
348
  if (_hot_count != 0) {
349
    xtty->print(" hot_count='%d'", _hot_count);
350
  }
351
  xtty->end_elem();
352
}
353

354

355
// ------------------------------------------------------------------
356
// CompileTask::log_task_start
357
void CompileTask::log_task_start(CompileLog* log)   {
358
  log->begin_head("task");
359
  log_task(log);
360
  log->end_head();
361
}
362

363

364
// ------------------------------------------------------------------
365
// CompileTask::log_task_done
366
void CompileTask::log_task_done(CompileLog* log) {
367
  Thread* thread = Thread::current();
368
  methodHandle method(thread, this->method());
369
  ResourceMark rm(thread);
370

371
  if (!_is_success) {
372
    assert(_failure_reason != nullptr, "missing");
373
    const char* reason = _failure_reason != nullptr ? _failure_reason : "unknown";
374
    log->begin_elem("failure reason='");
375
    log->text("%s", reason);
376
    log->print("'");
377
    log->end_elem();
378
  }
379

380
  // <task_done ... stamp='1.234'>  </task>
381
  log->begin_elem("task_done success='%d' nmsize='%d' count='%d'",
382
                  _is_success, _nm_content_size,
383
                  method->invocation_count());
384
  int bec = method->backedge_count();
385
  if (bec != 0)  log->print(" backedge_count='%d'", bec);
386
  // Note:  "_is_complete" is about to be set, but is not.
387
  if (_num_inlined_bytecodes != 0) {
388
    log->print(" inlined_bytes='%d'", _num_inlined_bytecodes);
389
  }
390
  log->stamp();
391
  log->end_elem();
392
  log->clear_identities();   // next task will have different CI
393
  log->tail("task");
394
  log->flush();
395
  log->mark_file_end();
396
}
397

398
// ------------------------------------------------------------------
399
// CompileTask::check_break_at_flags
400
bool CompileTask::check_break_at_flags() {
401
  int compile_id = this->_compile_id;
402
  bool is_osr = (_osr_bci != CompileBroker::standard_entry_bci);
403

404
  if (CICountOSR && is_osr && (compile_id == CIBreakAtOSR)) {
405
    return true;
406
  } else {
407
    return (compile_id == CIBreakAt);
408
  }
409
}
410

411
// ------------------------------------------------------------------
412
// CompileTask::print_inlining
413
void CompileTask::print_inlining_inner(outputStream* st, ciMethod* method, int inline_level, int bci, InliningResult result, const char* msg) {
414
  //         1234567
415
  st->print("        ");     // print timestamp
416
  //         1234
417
  st->print("     ");        // print compilation number
418

419
  // method attributes
420
  if (method->is_loaded()) {
421
    const char sync_char      = method->is_synchronized()        ? 's' : ' ';
422
    const char exception_char = method->has_exception_handlers() ? '!' : ' ';
423
    const char monitors_char  = method->has_monitor_bytecodes()  ? 'm' : ' ';
424

425
    // print method attributes
426
    st->print(" %c%c%c  ", sync_char, exception_char, monitors_char);
427
  } else {
428
    //         %s!bn
429
    st->print("      ");     // print method attributes
430
  }
431

432
  if (TieredCompilation) {
433
    st->print("  ");
434
  }
435
  st->print("     ");        // more indent
436
  st->print("    ");         // initial inlining indent
437

438
  for (int i = 0; i < inline_level; i++)  st->print("  ");
439

440
  st->print("@ %d  ", bci);  // print bci
441
  method->print_short_name(st);
442
  if (method->is_loaded())
443
    st->print(" (%d bytes)", method->code_size());
444
  else
445
    st->print(" (not loaded)");
446

447
  if (msg != nullptr) {
448
    st->print("   %s%s", result == InliningResult::SUCCESS ? "" : "failed to inline: ", msg);
449
  } else if (result == InliningResult::FAILURE) {
450
    st->print("   %s", "failed to inline");
451
  }
452
  st->cr();
453
}
454

455
void CompileTask::print_ul(const char* msg){
456
  LogTarget(Debug, jit, compilation) lt;
457
  if (lt.is_enabled()) {
458
    LogStream ls(lt);
459
    print(&ls, msg, /* short form */ true, /* cr */ true);
460
  }
461
}
462

463
void CompileTask::print_ul(const nmethod* nm, const char* msg) {
464
  LogTarget(Debug, jit, compilation) lt;
465
  if (lt.is_enabled()) {
466
    LogStream ls(lt);
467
    print_impl(&ls, nm->method(), nm->compile_id(),
468
               nm->comp_level(), nm->is_osr_method(),
469
               nm->is_osr_method() ? nm->osr_entry_bci() : -1,
470
               /*is_blocking*/ false,
471
               msg, /* short form */ true, /* cr */ true);
472
  }
473
}
474

475
void CompileTask::print_inlining_ul(ciMethod* method, int inline_level, int bci, InliningResult result, const char* msg) {
476
  LogTarget(Debug, jit, inlining) lt;
477
  if (lt.is_enabled()) {
478
    LogStream ls(lt);
479
    print_inlining_inner(&ls, method, inline_level, bci, result, msg);
480
  }
481
}
482

483

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

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

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

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