|
1 /* |
|
2 * Copyright (c) 1998, 2017, 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/compileTask.hpp" |
|
27 #include "compiler/compileLog.hpp" |
|
28 #include "compiler/compileBroker.hpp" |
|
29 #include "compiler/compilerDirectives.hpp" |
|
30 #include "logging/log.hpp" |
|
31 #include "logging/logStream.hpp" |
|
32 #include "memory/resourceArea.hpp" |
|
33 |
|
34 CompileTask* CompileTask::_task_free_list = NULL; |
|
35 #ifdef ASSERT |
|
36 int CompileTask::_num_allocated_tasks = 0; |
|
37 #endif |
|
38 |
|
39 /** |
|
40 * Allocate a CompileTask, from the free list if possible. |
|
41 */ |
|
42 CompileTask* CompileTask::allocate() { |
|
43 MutexLocker locker(CompileTaskAlloc_lock); |
|
44 CompileTask* task = NULL; |
|
45 |
|
46 if (_task_free_list != NULL) { |
|
47 task = _task_free_list; |
|
48 _task_free_list = task->next(); |
|
49 task->set_next(NULL); |
|
50 } else { |
|
51 task = new CompileTask(); |
|
52 DEBUG_ONLY(_num_allocated_tasks++;) |
|
53 assert (WhiteBoxAPI || JVMCI_ONLY(UseJVMCICompiler ||) _num_allocated_tasks < 10000, "Leaking compilation tasks?"); |
|
54 task->set_next(NULL); |
|
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 |
|
66 void CompileTask::free(CompileTask* task) { |
|
67 MutexLocker locker(CompileTaskAlloc_lock); |
|
68 if (!task->is_free()) { |
|
69 task->set_code(NULL); |
|
70 assert(!task->lock()->is_locked(), "Should not be locked when freed"); |
|
71 JNIHandles::destroy_global(task->_method_holder); |
|
72 JNIHandles::destroy_global(task->_hot_method_holder); |
|
73 |
|
74 task->set_is_free(true); |
|
75 task->set_next(_task_free_list); |
|
76 _task_free_list = task; |
|
77 } |
|
78 } |
|
79 |
|
80 |
|
81 void CompileTask::initialize(int compile_id, |
|
82 const methodHandle& method, |
|
83 int osr_bci, |
|
84 int comp_level, |
|
85 const methodHandle& hot_method, |
|
86 int hot_count, |
|
87 CompileTask::CompileReason compile_reason, |
|
88 bool is_blocking) { |
|
89 assert(!_lock->is_locked(), "bad locking"); |
|
90 |
|
91 Thread* thread = Thread::current(); |
|
92 _compile_id = compile_id; |
|
93 _method = method(); |
|
94 _method_holder = JNIHandles::make_global(Handle(thread, method->method_holder()->klass_holder())); |
|
95 _osr_bci = osr_bci; |
|
96 _is_blocking = is_blocking; |
|
97 JVMCI_ONLY(_has_waiter = CompileBroker::compiler(comp_level)->is_jvmci();) |
|
98 JVMCI_ONLY(_jvmci_compiler_thread = NULL;) |
|
99 _comp_level = comp_level; |
|
100 _num_inlined_bytecodes = 0; |
|
101 |
|
102 _is_complete = false; |
|
103 _is_success = false; |
|
104 _code_handle = NULL; |
|
105 |
|
106 _hot_method = NULL; |
|
107 _hot_method_holder = NULL; |
|
108 _hot_count = hot_count; |
|
109 _time_queued = 0; // tidy |
|
110 _compile_reason = compile_reason; |
|
111 _failure_reason = NULL; |
|
112 |
|
113 if (LogCompilation) { |
|
114 _time_queued = os::elapsed_counter(); |
|
115 if (hot_method.not_null()) { |
|
116 if (hot_method == method) { |
|
117 _hot_method = _method; |
|
118 } else { |
|
119 _hot_method = hot_method(); |
|
120 // only add loader or mirror if different from _method_holder |
|
121 _hot_method_holder = JNIHandles::make_global(Handle(thread, hot_method->method_holder()->klass_holder())); |
|
122 } |
|
123 } |
|
124 } |
|
125 |
|
126 _next = NULL; |
|
127 } |
|
128 |
|
129 /** |
|
130 * Returns the compiler for this task. |
|
131 */ |
|
132 AbstractCompiler* CompileTask::compiler() { |
|
133 return CompileBroker::compiler(_comp_level); |
|
134 } |
|
135 |
|
136 // ------------------------------------------------------------------ |
|
137 // CompileTask::code/set_code |
|
138 // |
|
139 nmethod* CompileTask::code() const { |
|
140 if (_code_handle == NULL) return NULL; |
|
141 CodeBlob *blob = _code_handle->code(); |
|
142 if (blob != NULL) { |
|
143 return blob->as_nmethod(); |
|
144 } |
|
145 return NULL; |
|
146 } |
|
147 |
|
148 void CompileTask::set_code(nmethod* nm) { |
|
149 if (_code_handle == NULL && nm == NULL) return; |
|
150 guarantee(_code_handle != NULL, ""); |
|
151 _code_handle->set_code(nm); |
|
152 if (nm == NULL) _code_handle = NULL; // drop the handle also |
|
153 } |
|
154 |
|
155 void CompileTask::mark_on_stack() { |
|
156 // Mark these methods as something redefine classes cannot remove. |
|
157 _method->set_on_stack(true); |
|
158 if (_hot_method != NULL) { |
|
159 _hot_method->set_on_stack(true); |
|
160 } |
|
161 } |
|
162 |
|
163 // RedefineClasses support |
|
164 void CompileTask::metadata_do(void f(Metadata*)) { |
|
165 f(method()); |
|
166 if (hot_method() != NULL && hot_method() != method()) { |
|
167 f(hot_method()); |
|
168 } |
|
169 } |
|
170 |
|
171 // ------------------------------------------------------------------ |
|
172 // CompileTask::print_line_on_error |
|
173 // |
|
174 // This function is called by fatal error handler when the thread |
|
175 // causing troubles is a compiler thread. |
|
176 // |
|
177 // Do not grab any lock, do not allocate memory. |
|
178 // |
|
179 // Otherwise it's the same as CompileTask::print_line() |
|
180 // |
|
181 void CompileTask::print_line_on_error(outputStream* st, char* buf, int buflen) { |
|
182 // print compiler name |
|
183 st->print("%s:", CompileBroker::compiler_name(comp_level())); |
|
184 print(st); |
|
185 } |
|
186 |
|
187 // ------------------------------------------------------------------ |
|
188 // CompileTask::print_tty |
|
189 void CompileTask::print_tty() { |
|
190 ttyLocker ttyl; // keep the following output all in one block |
|
191 // print compiler name if requested |
|
192 if (CIPrintCompilerName) { |
|
193 tty->print("%s:", CompileBroker::compiler_name(comp_level())); |
|
194 } |
|
195 print(tty); |
|
196 } |
|
197 |
|
198 // ------------------------------------------------------------------ |
|
199 // CompileTask::print_impl |
|
200 void CompileTask::print_impl(outputStream* st, Method* method, int compile_id, int comp_level, |
|
201 bool is_osr_method, int osr_bci, bool is_blocking, |
|
202 const char* msg, bool short_form, bool cr) { |
|
203 if (!short_form) { |
|
204 st->print("%7d ", (int) st->time_stamp().milliseconds()); // print timestamp |
|
205 } |
|
206 // print compiler name if requested |
|
207 if (CIPrintCompilerName) { |
|
208 st->print("%s:", CompileBroker::compiler_name(comp_level)); |
|
209 } |
|
210 st->print("%4d ", compile_id); // print compilation number |
|
211 |
|
212 // For unloaded methods the transition to zombie occurs after the |
|
213 // method is cleared so it's impossible to report accurate |
|
214 // information for that case. |
|
215 bool is_synchronized = false; |
|
216 bool has_exception_handler = false; |
|
217 bool is_native = false; |
|
218 if (method != NULL) { |
|
219 is_synchronized = method->is_synchronized(); |
|
220 has_exception_handler = method->has_exception_handler(); |
|
221 is_native = method->is_native(); |
|
222 } |
|
223 // method attributes |
|
224 const char compile_type = is_osr_method ? '%' : ' '; |
|
225 const char sync_char = is_synchronized ? 's' : ' '; |
|
226 const char exception_char = has_exception_handler ? '!' : ' '; |
|
227 const char blocking_char = is_blocking ? 'b' : ' '; |
|
228 const char native_char = is_native ? 'n' : ' '; |
|
229 |
|
230 // print method attributes |
|
231 st->print("%c%c%c%c%c ", compile_type, sync_char, exception_char, blocking_char, native_char); |
|
232 |
|
233 if (TieredCompilation) { |
|
234 if (comp_level != -1) st->print("%d ", comp_level); |
|
235 else st->print("- "); |
|
236 } |
|
237 st->print(" "); // more indent |
|
238 |
|
239 if (method == NULL) { |
|
240 st->print("(method)"); |
|
241 } else { |
|
242 method->print_short_name(st); |
|
243 if (is_osr_method) { |
|
244 st->print(" @ %d", osr_bci); |
|
245 } |
|
246 if (method->is_native()) |
|
247 st->print(" (native)"); |
|
248 else |
|
249 st->print(" (%d bytes)", method->code_size()); |
|
250 } |
|
251 |
|
252 if (msg != NULL) { |
|
253 st->print(" %s", msg); |
|
254 } |
|
255 if (cr) { |
|
256 st->cr(); |
|
257 } |
|
258 } |
|
259 |
|
260 void CompileTask::print_inline_indent(int inline_level, outputStream* st) { |
|
261 // 1234567 |
|
262 st->print(" "); // print timestamp |
|
263 // 1234 |
|
264 st->print(" "); // print compilation number |
|
265 // %s!bn |
|
266 st->print(" "); // print method attributes |
|
267 if (TieredCompilation) { |
|
268 st->print(" "); |
|
269 } |
|
270 st->print(" "); // more indent |
|
271 st->print(" "); // initial inlining indent |
|
272 for (int i = 0; i < inline_level; i++) st->print(" "); |
|
273 } |
|
274 |
|
275 // ------------------------------------------------------------------ |
|
276 // CompileTask::print_compilation |
|
277 void CompileTask::print(outputStream* st, const char* msg, bool short_form, bool cr) { |
|
278 bool is_osr_method = osr_bci() != InvocationEntryBci; |
|
279 print_impl(st, method(), compile_id(), comp_level(), is_osr_method, osr_bci(), is_blocking(), msg, short_form, cr); |
|
280 } |
|
281 |
|
282 // ------------------------------------------------------------------ |
|
283 // CompileTask::log_task |
|
284 void CompileTask::log_task(xmlStream* log) { |
|
285 Thread* thread = Thread::current(); |
|
286 methodHandle method(thread, this->method()); |
|
287 ResourceMark rm(thread); |
|
288 |
|
289 // <task id='9' method='M' osr_bci='X' level='1' blocking='1' stamp='1.234'> |
|
290 log->print(" compile_id='%d'", _compile_id); |
|
291 if (_osr_bci != CompileBroker::standard_entry_bci) { |
|
292 log->print(" compile_kind='osr'"); // same as nmethod::compile_kind |
|
293 } // else compile_kind='c2c' |
|
294 if (!method.is_null()) log->method(method); |
|
295 if (_osr_bci != CompileBroker::standard_entry_bci) { |
|
296 log->print(" osr_bci='%d'", _osr_bci); |
|
297 } |
|
298 if (_comp_level != CompLevel_highest_tier) { |
|
299 log->print(" level='%d'", _comp_level); |
|
300 } |
|
301 if (_is_blocking) { |
|
302 log->print(" blocking='1'"); |
|
303 } |
|
304 log->stamp(); |
|
305 } |
|
306 |
|
307 // ------------------------------------------------------------------ |
|
308 // CompileTask::log_task_queued |
|
309 void CompileTask::log_task_queued() { |
|
310 Thread* thread = Thread::current(); |
|
311 ttyLocker ttyl; |
|
312 ResourceMark rm(thread); |
|
313 |
|
314 xtty->begin_elem("task_queued"); |
|
315 log_task(xtty); |
|
316 assert(_compile_reason > CompileTask::Reason_None && _compile_reason < CompileTask::Reason_Count, "Valid values"); |
|
317 xtty->print(" comment='%s'", reason_name(_compile_reason)); |
|
318 |
|
319 if (_hot_method != NULL) { |
|
320 methodHandle hot(thread, _hot_method); |
|
321 methodHandle method(thread, _method); |
|
322 if (hot() != method()) { |
|
323 xtty->method(hot); |
|
324 } |
|
325 } |
|
326 if (_hot_count != 0) { |
|
327 xtty->print(" hot_count='%d'", _hot_count); |
|
328 } |
|
329 xtty->end_elem(); |
|
330 } |
|
331 |
|
332 |
|
333 // ------------------------------------------------------------------ |
|
334 // CompileTask::log_task_start |
|
335 void CompileTask::log_task_start(CompileLog* log) { |
|
336 log->begin_head("task"); |
|
337 log_task(log); |
|
338 log->end_head(); |
|
339 } |
|
340 |
|
341 |
|
342 // ------------------------------------------------------------------ |
|
343 // CompileTask::log_task_done |
|
344 void CompileTask::log_task_done(CompileLog* log) { |
|
345 Thread* thread = Thread::current(); |
|
346 methodHandle method(thread, this->method()); |
|
347 ResourceMark rm(thread); |
|
348 |
|
349 if (!_is_success) { |
|
350 const char* reason = _failure_reason != NULL ? _failure_reason : "unknown"; |
|
351 log->elem("failure reason='%s'", reason); |
|
352 } |
|
353 |
|
354 // <task_done ... stamp='1.234'> </task> |
|
355 nmethod* nm = code(); |
|
356 log->begin_elem("task_done success='%d' nmsize='%d' count='%d'", |
|
357 _is_success, nm == NULL ? 0 : nm->content_size(), |
|
358 method->invocation_count()); |
|
359 int bec = method->backedge_count(); |
|
360 if (bec != 0) log->print(" backedge_count='%d'", bec); |
|
361 // Note: "_is_complete" is about to be set, but is not. |
|
362 if (_num_inlined_bytecodes != 0) { |
|
363 log->print(" inlined_bytes='%d'", _num_inlined_bytecodes); |
|
364 } |
|
365 log->stamp(); |
|
366 log->end_elem(); |
|
367 log->clear_identities(); // next task will have different CI |
|
368 log->tail("task"); |
|
369 if (log->unflushed_count() > 2000) { |
|
370 log->flush(); |
|
371 } |
|
372 log->mark_file_end(); |
|
373 } |
|
374 |
|
375 // ------------------------------------------------------------------ |
|
376 // CompileTask::check_break_at_flags |
|
377 bool CompileTask::check_break_at_flags() { |
|
378 int compile_id = this->_compile_id; |
|
379 bool is_osr = (_osr_bci != CompileBroker::standard_entry_bci); |
|
380 |
|
381 if (CICountOSR && is_osr && (compile_id == CIBreakAtOSR)) { |
|
382 return true; |
|
383 } else { |
|
384 return (compile_id == CIBreakAt); |
|
385 } |
|
386 } |
|
387 |
|
388 // ------------------------------------------------------------------ |
|
389 // CompileTask::print_inlining |
|
390 void CompileTask::print_inlining_inner(outputStream* st, ciMethod* method, int inline_level, int bci, const char* msg) { |
|
391 // 1234567 |
|
392 st->print(" "); // print timestamp |
|
393 // 1234 |
|
394 st->print(" "); // print compilation number |
|
395 |
|
396 // method attributes |
|
397 if (method->is_loaded()) { |
|
398 const char sync_char = method->is_synchronized() ? 's' : ' '; |
|
399 const char exception_char = method->has_exception_handlers() ? '!' : ' '; |
|
400 const char monitors_char = method->has_monitor_bytecodes() ? 'm' : ' '; |
|
401 |
|
402 // print method attributes |
|
403 st->print(" %c%c%c ", sync_char, exception_char, monitors_char); |
|
404 } else { |
|
405 // %s!bn |
|
406 st->print(" "); // print method attributes |
|
407 } |
|
408 |
|
409 if (TieredCompilation) { |
|
410 st->print(" "); |
|
411 } |
|
412 st->print(" "); // more indent |
|
413 st->print(" "); // initial inlining indent |
|
414 |
|
415 for (int i = 0; i < inline_level; i++) st->print(" "); |
|
416 |
|
417 st->print("@ %d ", bci); // print bci |
|
418 method->print_short_name(st); |
|
419 if (method->is_loaded()) |
|
420 st->print(" (%d bytes)", method->code_size()); |
|
421 else |
|
422 st->print(" (not loaded)"); |
|
423 |
|
424 if (msg != NULL) { |
|
425 st->print(" %s", msg); |
|
426 } |
|
427 st->cr(); |
|
428 } |
|
429 |
|
430 void CompileTask::print_ul(const char* msg){ |
|
431 LogTarget(Debug, jit, compilation) lt; |
|
432 if (lt.is_enabled()) { |
|
433 LogStream ls(lt); |
|
434 print(&ls, msg, /* short form */ true, /* cr */ true); |
|
435 } |
|
436 } |
|
437 |
|
438 void CompileTask::print_ul(const nmethod* nm, const char* msg) { |
|
439 LogTarget(Debug, jit, compilation) lt; |
|
440 if (lt.is_enabled()) { |
|
441 LogStream ls(lt); |
|
442 print_impl(&ls, nm->method(), nm->compile_id(), |
|
443 nm->comp_level(), nm->is_osr_method(), |
|
444 nm->is_osr_method() ? nm->osr_entry_bci() : -1, |
|
445 /*is_blocking*/ false, |
|
446 msg, /* short form */ true, /* cr */ true); |
|
447 } |
|
448 } |
|
449 |
|
450 void CompileTask::print_inlining_ul(ciMethod* method, int inline_level, int bci, const char* msg) { |
|
451 LogTarget(Debug, jit, inlining) lt; |
|
452 if (lt.is_enabled()) { |
|
453 LogStream ls(lt); |
|
454 print_inlining_inner(&ls, method, inline_level, bci, msg); |
|
455 } |
|
456 } |
|
457 |