Mercurial > hg > graal-jvmci-8
comparison src/share/vm/compiler/compileBroker.cpp @ 22762:9d78d44d3aac
improved JVMCI support for blocking compilation (GRAAL-1387)
author | Doug Simon <doug.simon@oracle.com> |
---|---|
date | Fri, 08 Jan 2016 17:30:33 +0100 |
parents | 24fd08e99b35 |
children | 94b7354ef0e0 |
comparison
equal
deleted
inserted
replaced
22761:f2206f5bb62e | 22762:9d78d44d3aac |
---|---|
235 } | 235 } |
236 | 236 |
237 CompileTaskWrapper::CompileTaskWrapper(CompileTask* task) { | 237 CompileTaskWrapper::CompileTaskWrapper(CompileTask* task) { |
238 CompilerThread* thread = CompilerThread::current(); | 238 CompilerThread* thread = CompilerThread::current(); |
239 thread->set_task(task); | 239 thread->set_task(task); |
240 #ifdef COMPILERJVMCI | |
241 if (task->is_blocking() && CompileBroker::compiler(task->comp_level())->is_jvmci()) { | |
242 task->set_jvmci_compiler_thread(thread); | |
243 } | |
244 #endif | |
240 CompileLog* log = thread->log(); | 245 CompileLog* log = thread->log(); |
241 if (log != NULL) task->log_task_start(log); | 246 if (log != NULL) task->log_task_start(log); |
242 } | 247 } |
243 | 248 |
244 CompileTaskWrapper::~CompileTaskWrapper() { | 249 CompileTaskWrapper::~CompileTaskWrapper() { |
254 { | 259 { |
255 MutexLocker notifier(task->lock(), thread); | 260 MutexLocker notifier(task->lock(), thread); |
256 task->mark_complete(); | 261 task->mark_complete(); |
257 #ifdef COMPILERJVMCI | 262 #ifdef COMPILERJVMCI |
258 if (CompileBroker::compiler(task->comp_level())->is_jvmci()) { | 263 if (CompileBroker::compiler(task->comp_level())->is_jvmci()) { |
259 // Blocking JVMCI compilations are performed with a timeout so as | 264 if (!task->has_waiter()) { |
260 // to avoid deadlock between an application thread and a JVMCI | 265 // The waiting thread timed out and thus did not free the task. |
261 // compiler thread (both of which execute Java code). | |
262 if (task->has_waiter()) { | |
263 // Notify the waiting thread that the compilation has completed | |
264 // and let it free the CompileTask. | |
265 task->lock()->notify_all(); | |
266 } else { | |
267 // The waiting thread timed out did not free the task. | |
268 free_task = true; | 266 free_task = true; |
269 } | 267 } |
270 } else { | 268 task->set_jvmci_compiler_thread(NULL); |
269 } | |
270 #endif | |
271 if (!free_task) { | |
271 // Notify the waiting thread that the compilation has completed. | 272 // Notify the waiting thread that the compilation has completed. |
272 task->lock()->notify_all(); | 273 task->lock()->notify_all(); |
273 } | 274 } |
274 #else | |
275 // Notify the waiting thread that the compilation has completed. | |
276 task->lock()->notify_all(); | |
277 #endif | |
278 } | 275 } |
279 if (free_task) { | 276 if (free_task) { |
280 // The task can only be freed once the task lock is released. | 277 // The task can only be freed once the task lock is released. |
281 CompileTask::free(task); | 278 CompileTask::free(task); |
282 } | 279 } |
306 _task_free_list = task->next(); | 303 _task_free_list = task->next(); |
307 task->set_next(NULL); | 304 task->set_next(NULL); |
308 } else { | 305 } else { |
309 task = new CompileTask(); | 306 task = new CompileTask(); |
310 DEBUG_ONLY(_num_allocated_tasks++;) | 307 DEBUG_ONLY(_num_allocated_tasks++;) |
311 assert (_num_allocated_tasks < 10000, "Leaking compilation tasks?"); | 308 NOT_COMPILERJVMCI(assert (_num_allocated_tasks < 10000, "Leaking compilation tasks?");) |
312 task->set_next(NULL); | 309 task->set_next(NULL); |
313 task->set_is_free(true); | 310 task->set_is_free(true); |
314 } | 311 } |
315 assert(task->is_free(), "Task must be free."); | 312 assert(task->is_free(), "Task must be free."); |
316 task->set_is_free(false); | 313 task->set_is_free(false); |
349 _method = method(); | 346 _method = method(); |
350 _method_holder = JNIHandles::make_global(method->method_holder()->klass_holder()); | 347 _method_holder = JNIHandles::make_global(method->method_holder()->klass_holder()); |
351 _osr_bci = osr_bci; | 348 _osr_bci = osr_bci; |
352 _is_blocking = is_blocking; | 349 _is_blocking = is_blocking; |
353 COMPILERJVMCI_PRESENT(_has_waiter = CompileBroker::compiler(comp_level)->is_jvmci();) | 350 COMPILERJVMCI_PRESENT(_has_waiter = CompileBroker::compiler(comp_level)->is_jvmci();) |
351 COMPILERJVMCI_PRESENT(_jvmci_compiler_thread = NULL;) | |
354 _comp_level = comp_level; | 352 _comp_level = comp_level; |
355 _num_inlined_bytecodes = 0; | 353 _num_inlined_bytecodes = 0; |
356 | 354 |
357 _is_complete = false; | 355 _is_complete = false; |
358 _is_success = false; | 356 _is_success = false; |
1711 blocking); | 1709 blocking); |
1712 queue->add(new_task); | 1710 queue->add(new_task); |
1713 return new_task; | 1711 return new_task; |
1714 } | 1712 } |
1715 | 1713 |
1716 // 1 second should be long enough to complete most JVMCI compilations | 1714 #ifdef COMPILERJVMCI |
1717 // and not too long to stall a blocking JVMCI compilation that | 1715 // The number of milliseconds to wait before checking if the |
1718 // is trying to acquire a lock held by the app thread that submitted the | 1716 // JVMCI compiler has become blocked during compilation. |
1719 // compilation. | 1717 static const long BLOCKING_JVMCI_COMPILATION_WAIT_TIMESLICE = 500; |
1720 static const long BLOCKING_JVMCI_COMPILATION_TIMEOUT = 1000; | 1718 |
1719 // The number of successive times the above check is allowed to | |
1720 // see a blocked JVMCI compiler thread before unblocking the | |
1721 // thread waiting for the compilation to finish. | |
1722 static const int BLOCKING_JVMCI_COMPILATION_WAIT_TO_UNBLOCK_ATTEMPTS = 5; | |
1723 | |
1724 /** | |
1725 * Waits for a JVMCI compiler to complete a given task. This thread | |
1726 * waits until either the task completes or it sees the JVMCI compiler | |
1727 * thread is blocked for N consecutive milliseconds where N is | |
1728 * BLOCKING_JVMCI_COMPILATION_WAIT_TIMESLICE * | |
1729 * BLOCKING_JVMCI_COMPILATION_WAIT_TO_UNBLOCK_ATTEMPTS. | |
1730 * | |
1731 * @return true if this thread needs to free/recycle the task | |
1732 */ | |
1733 bool CompileBroker::wait_for_jvmci_completion(CompileTask* task, JavaThread* thread) { | |
1734 MutexLocker waiter(task->lock(), thread); | |
1735 int consecutively_blocked = 0; | |
1736 while (task->lock()->wait(!Mutex::_no_safepoint_check_flag, BLOCKING_JVMCI_COMPILATION_WAIT_TIMESLICE)) { | |
1737 CompilerThread* jvmci_compiler_thread = task->jvmci_compiler_thread(); | |
1738 if (jvmci_compiler_thread != NULL) { | |
1739 JavaThreadState state; | |
1740 { | |
1741 // A JVMCI compiler thread should not disappear at this point | |
1742 // but let's be extra safe. | |
1743 MutexLocker mu(Threads_lock, thread); | |
1744 state = jvmci_compiler_thread->thread_state(); | |
1745 } | |
1746 if (state == _thread_blocked) { | |
1747 if (++consecutively_blocked == BLOCKING_JVMCI_COMPILATION_WAIT_TO_UNBLOCK_ATTEMPTS) { | |
1748 if (_compilation_log != NULL) { | |
1749 _compilation_log->log_failure(thread, task, "compilation timed out", NULL); | |
1750 } | |
1751 if (PrintCompilation) { | |
1752 task->print_compilation(tty, "compilation timed out"); | |
1753 } | |
1754 break; | |
1755 } | |
1756 } else { | |
1757 consecutively_blocked = 0; | |
1758 } | |
1759 } else { | |
1760 // Still waiting on JVMCI compiler queue | |
1761 } | |
1762 } | |
1763 task->clear_waiter(); | |
1764 return task->is_complete(); | |
1765 } | |
1766 #endif | |
1721 | 1767 |
1722 /** | 1768 /** |
1723 * Wait for the compilation task to complete. | 1769 * Wait for the compilation task to complete. |
1724 */ | 1770 */ |
1725 void CompileBroker::wait_for_completion(CompileTask* task) { | 1771 void CompileBroker::wait_for_completion(CompileTask* task) { |
1735 | 1781 |
1736 methodHandle method(thread, task->method()); | 1782 methodHandle method(thread, task->method()); |
1737 bool free_task = true; | 1783 bool free_task = true; |
1738 #ifdef COMPILERJVMCI | 1784 #ifdef COMPILERJVMCI |
1739 if (compiler(task->comp_level())->is_jvmci()) { | 1785 if (compiler(task->comp_level())->is_jvmci()) { |
1740 { | 1786 free_task = wait_for_jvmci_completion(task, thread); |
1741 MutexLocker waiter(task->lock(), thread); | |
1742 // No need to check if compilation has completed - just | |
1743 // rely on the time out. The JVMCI compiler thread will | |
1744 // recycle the CompileTask. | |
1745 task->lock()->wait(!Mutex::_no_safepoint_check_flag, BLOCKING_JVMCI_COMPILATION_TIMEOUT); | |
1746 // If the compilation completes while has_waiter is true then | |
1747 // this thread is responsible for freeing the task. Otherwise | |
1748 // the compiler thread will free the task. | |
1749 task->clear_waiter(); | |
1750 free_task = task->is_complete(); | |
1751 } | |
1752 } else | 1787 } else |
1753 #endif | 1788 #endif |
1754 { | 1789 { |
1755 MutexLocker waiter(task->lock(), thread); | 1790 MutexLocker waiter(task->lock(), thread); |
1756 while (!task->is_complete() && !is_compilation_disabled_forever()) { | 1791 while (!task->is_complete() && !is_compilation_disabled_forever()) { |