Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/hotspot/share/compiler/compileTask.cpp
40930 views
1
/*
2
* Copyright (c) 1998, 2021, 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
38
CompileTask* CompileTask::_task_free_list = NULL;
39
40
/**
41
* Allocate a CompileTask, from the free list if possible.
42
*/
43
CompileTask* CompileTask::allocate() {
44
MutexLocker locker(CompileTaskAlloc_lock);
45
CompileTask* task = NULL;
46
47
if (_task_free_list != NULL) {
48
task = _task_free_list;
49
_task_free_list = task->next();
50
task->set_next(NULL);
51
} else {
52
task = new CompileTask();
53
task->set_next(NULL);
54
task->set_is_free(true);
55
}
56
assert(task->is_free(), "Task must be free.");
57
task->set_is_free(false);
58
return task;
59
}
60
61
/**
62
* Add a task to the free list.
63
*/
64
void CompileTask::free(CompileTask* task) {
65
MutexLocker locker(CompileTaskAlloc_lock);
66
if (!task->is_free()) {
67
task->set_code(NULL);
68
assert(!task->lock()->is_locked(), "Should not be locked when freed");
69
if ((task->_method_holder != NULL && JNIHandles::is_weak_global_handle(task->_method_holder)) ||
70
(task->_hot_method_holder != NULL && 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 != NULL) {
78
os::free((void*) task->_failure_reason);
79
}
80
task->_failure_reason = NULL;
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 = NULL;)
107
_comp_level = comp_level;
108
_num_inlined_bytecodes = 0;
109
110
_is_complete = false;
111
_is_success = false;
112
_code_handle = NULL;
113
114
_hot_method = NULL;
115
_hot_method_holder = NULL;
116
_hot_count = hot_count;
117
_time_queued = os::elapsed_counter();
118
_time_started = 0;
119
_compile_reason = compile_reason;
120
_failure_reason = NULL;
121
_failure_reason_on_C_heap = false;
122
123
if (LogCompilation) {
124
if (hot_method.not_null()) {
125
if (hot_method == method) {
126
_hot_method = _method;
127
} else {
128
_hot_method = hot_method();
129
// only add loader or mirror if different from _method_holder
130
_hot_method_holder = JNIHandles::make_weak_global(Handle(thread, hot_method->method_holder()->klass_holder()));
131
}
132
}
133
}
134
135
_next = NULL;
136
}
137
138
/**
139
* Returns the compiler for this task.
140
*/
141
AbstractCompiler* CompileTask::compiler() {
142
return CompileBroker::compiler(_comp_level);
143
}
144
145
// Replace weak handles by strong handles to avoid unloading during compilation.
146
CompileTask* CompileTask::select_for_compilation() {
147
if (is_unloaded()) {
148
// Guard against concurrent class unloading
149
return NULL;
150
}
151
Thread* thread = Thread::current();
152
assert(_method->method_holder()->is_loader_alive(), "should be alive");
153
Handle method_holder(thread, _method->method_holder()->klass_holder());
154
JNIHandles::destroy_weak_global(_method_holder);
155
JNIHandles::destroy_weak_global(_hot_method_holder);
156
_method_holder = JNIHandles::make_global(method_holder);
157
if (_hot_method != NULL) {
158
_hot_method_holder = JNIHandles::make_global(Handle(thread, _hot_method->method_holder()->klass_holder()));
159
}
160
return this;
161
}
162
163
// ------------------------------------------------------------------
164
// CompileTask::code/set_code
165
//
166
nmethod* CompileTask::code() const {
167
if (_code_handle == NULL) return NULL;
168
CodeBlob *blob = _code_handle->code();
169
if (blob != NULL) {
170
return blob->as_nmethod();
171
}
172
return NULL;
173
}
174
175
void CompileTask::set_code(nmethod* nm) {
176
if (_code_handle == NULL && nm == NULL) return;
177
guarantee(_code_handle != NULL, "");
178
_code_handle->set_code(nm);
179
if (nm == NULL) _code_handle = NULL; // drop the handle also
180
}
181
182
void CompileTask::mark_on_stack() {
183
if (is_unloaded()) {
184
return;
185
}
186
// Mark these methods as something redefine classes cannot remove.
187
_method->set_on_stack(true);
188
if (_hot_method != NULL) {
189
_hot_method->set_on_stack(true);
190
}
191
}
192
193
bool CompileTask::is_unloaded() const {
194
return _method_holder != NULL && JNIHandles::is_weak_global_handle(_method_holder) && JNIHandles::is_global_weak_cleared(_method_holder);
195
}
196
197
// RedefineClasses support
198
void CompileTask::metadata_do(MetadataClosure* f) {
199
if (is_unloaded()) {
200
return;
201
}
202
f->do_metadata(method());
203
if (hot_method() != NULL && hot_method() != method()) {
204
f->do_metadata(hot_method());
205
}
206
}
207
208
// ------------------------------------------------------------------
209
// CompileTask::print_line_on_error
210
//
211
// This function is called by fatal error handler when the thread
212
// causing troubles is a compiler thread.
213
//
214
// Do not grab any lock, do not allocate memory.
215
//
216
// Otherwise it's the same as CompileTask::print_line()
217
//
218
void CompileTask::print_line_on_error(outputStream* st, char* buf, int buflen) {
219
// print compiler name
220
st->print("%s:", CompileBroker::compiler_name(comp_level()));
221
print(st);
222
}
223
224
// ------------------------------------------------------------------
225
// CompileTask::print_tty
226
void CompileTask::print_tty() {
227
ttyLocker ttyl; // keep the following output all in one block
228
// print compiler name if requested
229
if (CIPrintCompilerName) {
230
tty->print("%s:", CompileBroker::compiler_name(comp_level()));
231
}
232
print(tty);
233
}
234
235
// ------------------------------------------------------------------
236
// CompileTask::print_impl
237
void CompileTask::print_impl(outputStream* st, Method* method, int compile_id, int comp_level,
238
bool is_osr_method, int osr_bci, bool is_blocking,
239
const char* msg, bool short_form, bool cr,
240
jlong time_queued, jlong time_started) {
241
if (!short_form) {
242
// Print current time
243
st->print("%7d ", (int)tty->time_stamp().milliseconds());
244
if (Verbose && time_queued != 0) {
245
// Print time in queue and time being processed by compiler thread
246
jlong now = os::elapsed_counter();
247
st->print("%d ", (int)TimeHelper::counter_to_millis(now-time_queued));
248
if (time_started != 0) {
249
st->print("%d ", (int)TimeHelper::counter_to_millis(now-time_started));
250
}
251
}
252
}
253
// print compiler name if requested
254
if (CIPrintCompilerName) {
255
st->print("%s:", CompileBroker::compiler_name(comp_level));
256
}
257
st->print("%4d ", compile_id); // print compilation number
258
259
// For unloaded methods the transition to zombie occurs after the
260
// method is cleared so it's impossible to report accurate
261
// information for that case.
262
bool is_synchronized = false;
263
bool has_exception_handler = false;
264
bool is_native = false;
265
if (method != NULL) {
266
is_synchronized = method->is_synchronized();
267
has_exception_handler = method->has_exception_handler();
268
is_native = method->is_native();
269
}
270
// method attributes
271
const char compile_type = is_osr_method ? '%' : ' ';
272
const char sync_char = is_synchronized ? 's' : ' ';
273
const char exception_char = has_exception_handler ? '!' : ' ';
274
const char blocking_char = is_blocking ? 'b' : ' ';
275
const char native_char = is_native ? 'n' : ' ';
276
277
// print method attributes
278
st->print("%c%c%c%c%c ", compile_type, sync_char, exception_char, blocking_char, native_char);
279
280
if (TieredCompilation) {
281
if (comp_level != -1) st->print("%d ", comp_level);
282
else st->print("- ");
283
}
284
st->print(" "); // more indent
285
286
if (method == NULL) {
287
st->print("(method)");
288
} else {
289
method->print_short_name(st);
290
if (is_osr_method) {
291
st->print(" @ %d", osr_bci);
292
}
293
if (method->is_native())
294
st->print(" (native)");
295
else
296
st->print(" (%d bytes)", method->code_size());
297
}
298
299
if (msg != NULL) {
300
st->print(" %s", msg);
301
}
302
if (cr) {
303
st->cr();
304
}
305
}
306
307
void CompileTask::print_inline_indent(int inline_level, outputStream* st) {
308
// 1234567
309
st->print(" "); // print timestamp
310
// 1234
311
st->print(" "); // print compilation number
312
// %s!bn
313
st->print(" "); // print method attributes
314
if (TieredCompilation) {
315
st->print(" ");
316
}
317
st->print(" "); // more indent
318
st->print(" "); // initial inlining indent
319
for (int i = 0; i < inline_level; i++) st->print(" ");
320
}
321
322
// ------------------------------------------------------------------
323
// CompileTask::print_compilation
324
void CompileTask::print(outputStream* st, const char* msg, bool short_form, bool cr) {
325
bool is_osr_method = osr_bci() != InvocationEntryBci;
326
print_impl(st, is_unloaded() ? NULL : method(), compile_id(), comp_level(), is_osr_method, osr_bci(), is_blocking(), msg, short_form, cr, _time_queued, _time_started);
327
}
328
329
// ------------------------------------------------------------------
330
// CompileTask::log_task
331
void CompileTask::log_task(xmlStream* log) {
332
Thread* thread = Thread::current();
333
methodHandle method(thread, this->method());
334
ResourceMark rm(thread);
335
336
// <task id='9' method='M' osr_bci='X' level='1' blocking='1' stamp='1.234'>
337
log->print(" compile_id='%d'", _compile_id);
338
if (_osr_bci != CompileBroker::standard_entry_bci) {
339
log->print(" compile_kind='osr'"); // same as nmethod::compile_kind
340
} // else compile_kind='c2c'
341
if (!method.is_null()) log->method(method());
342
if (_osr_bci != CompileBroker::standard_entry_bci) {
343
log->print(" osr_bci='%d'", _osr_bci);
344
}
345
if (_comp_level != CompilationPolicy::highest_compile_level()) {
346
log->print(" level='%d'", _comp_level);
347
}
348
if (_is_blocking) {
349
log->print(" blocking='1'");
350
}
351
log->stamp();
352
}
353
354
// ------------------------------------------------------------------
355
// CompileTask::log_task_queued
356
void CompileTask::log_task_queued() {
357
ttyLocker ttyl;
358
ResourceMark rm;
359
360
xtty->begin_elem("task_queued");
361
log_task(xtty);
362
assert(_compile_reason > CompileTask::Reason_None && _compile_reason < CompileTask::Reason_Count, "Valid values");
363
xtty->print(" comment='%s'", reason_name(_compile_reason));
364
365
if (_hot_method != NULL && _hot_method != _method) {
366
xtty->method(_hot_method);
367
}
368
if (_hot_count != 0) {
369
xtty->print(" hot_count='%d'", _hot_count);
370
}
371
xtty->end_elem();
372
}
373
374
375
// ------------------------------------------------------------------
376
// CompileTask::log_task_start
377
void CompileTask::log_task_start(CompileLog* log) {
378
log->begin_head("task");
379
log_task(log);
380
log->end_head();
381
}
382
383
384
// ------------------------------------------------------------------
385
// CompileTask::log_task_done
386
void CompileTask::log_task_done(CompileLog* log) {
387
Thread* thread = Thread::current();
388
methodHandle method(thread, this->method());
389
ResourceMark rm(thread);
390
391
if (!_is_success) {
392
assert(_failure_reason != NULL, "missing");
393
const char* reason = _failure_reason != NULL ? _failure_reason : "unknown";
394
log->begin_elem("failure reason='");
395
log->text("%s", reason);
396
log->print("'");
397
log->end_elem();
398
}
399
400
// <task_done ... stamp='1.234'> </task>
401
nmethod* nm = code();
402
log->begin_elem("task_done success='%d' nmsize='%d' count='%d'",
403
_is_success, nm == NULL ? 0 : nm->content_size(),
404
method->invocation_count());
405
int bec = method->backedge_count();
406
if (bec != 0) log->print(" backedge_count='%d'", bec);
407
// Note: "_is_complete" is about to be set, but is not.
408
if (_num_inlined_bytecodes != 0) {
409
log->print(" inlined_bytes='%d'", _num_inlined_bytecodes);
410
}
411
log->stamp();
412
log->end_elem();
413
log->clear_identities(); // next task will have different CI
414
log->tail("task");
415
log->flush();
416
log->mark_file_end();
417
}
418
419
// ------------------------------------------------------------------
420
// CompileTask::check_break_at_flags
421
bool CompileTask::check_break_at_flags() {
422
int compile_id = this->_compile_id;
423
bool is_osr = (_osr_bci != CompileBroker::standard_entry_bci);
424
425
if (CICountOSR && is_osr && (compile_id == CIBreakAtOSR)) {
426
return true;
427
} else {
428
return (compile_id == CIBreakAt);
429
}
430
}
431
432
// ------------------------------------------------------------------
433
// CompileTask::print_inlining
434
void CompileTask::print_inlining_inner(outputStream* st, ciMethod* method, int inline_level, int bci, const char* msg) {
435
// 1234567
436
st->print(" "); // print timestamp
437
// 1234
438
st->print(" "); // print compilation number
439
440
// method attributes
441
if (method->is_loaded()) {
442
const char sync_char = method->is_synchronized() ? 's' : ' ';
443
const char exception_char = method->has_exception_handlers() ? '!' : ' ';
444
const char monitors_char = method->has_monitor_bytecodes() ? 'm' : ' ';
445
446
// print method attributes
447
st->print(" %c%c%c ", sync_char, exception_char, monitors_char);
448
} else {
449
// %s!bn
450
st->print(" "); // print method attributes
451
}
452
453
if (TieredCompilation) {
454
st->print(" ");
455
}
456
st->print(" "); // more indent
457
st->print(" "); // initial inlining indent
458
459
for (int i = 0; i < inline_level; i++) st->print(" ");
460
461
st->print("@ %d ", bci); // print bci
462
method->print_short_name(st);
463
if (method->is_loaded())
464
st->print(" (%d bytes)", method->code_size());
465
else
466
st->print(" (not loaded)");
467
468
if (msg != NULL) {
469
st->print(" %s", msg);
470
}
471
st->cr();
472
}
473
474
void CompileTask::print_ul(const char* msg){
475
LogTarget(Debug, jit, compilation) lt;
476
if (lt.is_enabled()) {
477
LogStream ls(lt);
478
print(&ls, msg, /* short form */ true, /* cr */ true);
479
}
480
}
481
482
void CompileTask::print_ul(const nmethod* nm, const char* msg) {
483
LogTarget(Debug, jit, compilation) lt;
484
if (lt.is_enabled()) {
485
LogStream ls(lt);
486
print_impl(&ls, nm->method(), nm->compile_id(),
487
nm->comp_level(), nm->is_osr_method(),
488
nm->is_osr_method() ? nm->osr_entry_bci() : -1,
489
/*is_blocking*/ false,
490
msg, /* short form */ true, /* cr */ true);
491
}
492
}
493
494
void CompileTask::print_inlining_ul(ciMethod* method, int inline_level, int bci, const char* msg) {
495
LogTarget(Debug, jit, inlining) lt;
496
if (lt.is_enabled()) {
497
LogStream ls(lt);
498
print_inlining_inner(&ls, method, inline_level, bci, msg);
499
}
500
}
501
502
503