[9] RFR(S): JDK-8040798: compiler/startup/SmallCodeCacheStartup.java timed out in RT_Baseline
Albert
albert.noll at oracle.com
Mon Apr 28 05:36:52 UTC 2014
Hi,
could I get a second review?
Best,
Albert
On 04/25/2014 07:44 AM, Albert wrote:
> Thank you, Igor.
>
> Best,
> Albert
> On 04/24/2014 10:07 PM, Igor Veresov wrote:
>> This looks good to me.
>>
>> igor
>>
>> On Apr 24, 2014, at 3:50 AM, Albert <albert.noll at oracle.com> wrote:
>>
>>> Hi Igor,
>>>
>>> you are right. I implemented a new version based on your suggestions.
>>> Here is the new webrev:
>>> http://cr.openjdk.java.net/~anoll/8040798/webrev.02/
>>> Best,
>>> Albert
>>>
>>>
>>> On 04/23/2014 09:49 PM, Igor Veresov wrote:
>>>> Albert,
>>>>
>>>> You’re doing notify_all() on the *compile queue* lock, but the
>>>> waiting happens on one of *task* locks (there is a separate lock
>>>> for each task). I think you have to call notify() for each
>>>> individual task lock as you are removing the tasks for the queue.
>>>>
>>>> Also, you definitely don’t want to do an actual delete of the task
>>>> (like in delete_all()). You can’t delete the task, because later in
>>>> wait_for_completion() you check things like is_complete() and do
>>>> free_task(), and you’re actually using the memory that has already
>>>> been freed. So, perhaps you should implement something like
>>>> free_all() instead that would remove the elements from queue and
>>>> call free_task for each of them to put them back on the free list
>>>> (and call notify() for each of them to wake the waiters). I think
>>>> it’s ok if you just leave the tasks on the free list after that.
>>>>
>>>> You should however take care not to call free_task() multiple times
>>>> (one time in free(former delete)_all() the other time in
>>>> wait_for_completion()). Perhaps you need another flag to check for
>>>> that, or you can just assume that if it’s a part of the compile
>>>> shutdown the free_task() in wait_for_completion() can be skipped.
>>>> You would need to check for this flag in the loop in
>>>> wait_for_completion() as well. So in addition to check for
>>>> is_completed() you would check for is_freed() (which you’ll have to
>>>> add) or is_compilation_disabled_forever() like you did before.
>>>>
>>>> igor
>>>>
>>>> On Apr 23, 2014, at 1:22 AM, Albert <albert.noll at oracle.com> wrote:
>>>>
>>>>> Igor, Vladimir, thanks for looking at this.
>>>>>
>>>>> @Igor: You are right. If we do the notify in delete_all(), all
>>>>> threads that wait on the lock of a compilation task
>>>>> will wake up. I removed the timed wait in
>>>>> CompileBroker::wait_for_completion() since I think it is not needed
>>>>> anymore.
>>>>>
>>>>> @Vladimir: Please see comments inline:
>>>>>
>>>>> Here is the new webrev:
>>>>> http://cr.openjdk.java.net/~anoll/8040798/webrev.01/
>>>>>
>>>>>
>>>>> On 04/22/2014 07:36 PM, Vladimir Kozlov wrote:
>>>>>> Hi Albert,
>>>>>>
>>>>>> compileBroker.hpp I think you want:
>>>>>>
>>>>>> NOT_PRODUCT( void print(); )
>>>>>>
>>>>> Done.
>>>>>> and you need to use #ifndef PRODUCT in compileBroker.cpp.
>>>>>>
>>>>> Done.
>>>>>> Next comment is not finished:
>>>>>> + // Delete all queued compilation tasks to make
>>>>>>
>>>>> Done.
>>>>>> We have 2 queues (c1 and C2). Does it means that C1 compilation
>>>>>> may block C2 compilation too?:
>>>>>>
>>>>> Yes, I think we have a single bit per Method*.
>>>>>> + /**
>>>>>> + * See if this compilation is already requested.
>>>>>> + *
>>>>>> + * Implementation note: there is only a single "is in queue" bit
>>>>>> + * for each method. This means that the check below is overly
>>>>>> + * conservative in the sense that an osr compilation in the queue
>>>>>> + * will block a normal compilation from entering the queue (and
>>>>>> vice
>>>>>> + * versa). This can be remedied by a full queue search to
>>>>>> disambiguate
>>>>>> + * cases. If it is deemed profitable, this may be done.
>>>>>> + */
>>>>>> + bool CompileBroker::compilation_is_in_queue(methodHandle method) {
>>>>>>
>>>>>>
>>>>>> Why next code in CompileBroker::compile_method() is not working?:
>>>>>>
>>>>> Do you mean why that code does not prevent the deadlock?
>>>>>
>>>>> I think that code does not cover the following scenario:
>>>>> 1) All compiler threads wait for new tasks
>>>>> 2) We put a blocking task in the compilation queue and wake up the
>>>>> compiler thread
>>>>> 3) The Java thread that issued the blocking compilation calls
>>>>> wait() on the compilation task
>>>>> 4) We run out of code cache and shut down compilation
>>>>> 5) All compiler threads exit the while loop in CompileQueue::get()
>>>>> 6) The Java thread blocks forever.
>>>>>
>>>>> Best,
>>>>> Albert
>>>>>> // If the compiler is shut off due to code cache getting full
>>>>>> // fail out now so blocking compiles dont hang the java thread
>>>>>> if (!should_compile_new_jobs()) {
>>>>>> CompilationPolicy::policy()->delay_compilation(method());
>>>>>> return NULL;
>>>>>> }
>>>>>> compile_method_base(method, osr_bci, comp_level, hot_method,
>>>>>> hot_count, comment, THREAD);
>>>>>>
>>>>>> Thanks,
>>>>>> Vladimir
>>>>>>
>>>>>> On 4/22/14 6:42 AM, Albert wrote:
>>>>>>> Hi,
>>>>>>>
>>>>>>> could I get reviews for this small change?
>>>>>>>
>>>>>>> Bug:
>>>>>>> https://bugs.openjdk.java.net/browse/JDK-8040798
>>>>>>>
>>>>>>> Problem:
>>>>>>> The test starts the JVM with 3m code cache and 64 compiler
>>>>>>> threads. As a
>>>>>>> result, it is very likely
>>>>>>> that not all compiler threads can be started due to insufficient
>>>>>>> space
>>>>>>> in the code cache. It is also
>>>>>>> possible that the compiler runtime initialization of C1 and/or
>>>>>>> C2 fails.
>>>>>>> There is a race between a
>>>>>>> the blocking compilations (the test is started with -Xcomp) and the
>>>>>>> process of shutting down the
>>>>>>> compilers. More specifically, it can happen that (1) a blocking
>>>>>>> compilation task is put into a compilation
>>>>>>> queue, (2) the compilers are shut down, and (3) the application
>>>>>>> thread
>>>>>>> waits forever until the compilation
>>>>>>> completes (The compilation will never complete, since all compiler
>>>>>>> threads are exited).
>>>>>>>
>>>>>>> Solution:
>>>>>>> Add a timeout to the wait() that waits for a compilation to
>>>>>>> complete and
>>>>>>> check if compilation is shut down
>>>>>>> forever. Furthermore, if we shut down the compiler runtimes,
>>>>>>> make sure
>>>>>>> that we use the interpreter to
>>>>>>> continue execution. The changes that fix the bug are in the
>>>>>>> following
>>>>>>> functions:
>>>>>>>
>>>>>>> CompileBroker::wait_for_completion(CompileTask* task)
>>>>>>> shutdown_compiler_runtime(AbstractCompiler* comp,
>>>>>>> CompilerThread* thread)
>>>>>>>
>>>>>>>
>>>>>>> The patch also removes the destruction of the compile queue
>>>>>>> objects in
>>>>>>> shutdown_compiler_runtime().
>>>>>>> The destruction is removed, since it does not reclaim significant
>>>>>>> portions of memory, but possible introduces
>>>>>>> problems, since pointers to the compile queues can be used at other
>>>>>>> locations in the code. An assert ensures
>>>>>>> that no more tasks are put into a compilation queue once the
>>>>>>> compilers
>>>>>>> have been shut down.
>>>>>>>
>>>>>>> In addition, the patch adds two locks in:
>>>>>>>
>>>>>>> void CompileBroker::mark_on_stack()
>>>>>>>
>>>>>>>
>>>>>>> The two locks ensure that compilation tasks are not removed from
>>>>>>> the
>>>>>>> compilation queue or freed by a
>>>>>>> different (compiler) thread while the method mark_on_stack is
>>>>>>> executed.
>>>>>>> I am not really sure if that lock
>>>>>>> is needed. However, the lock seems to prevent concurrent
>>>>>>> read/writes of
>>>>>>> the compilation queue.
>>>>>>>
>>>>>>> The rest of the changes are simple optional refactorings.
>>>>>>>
>>>>>>> Testing:
>>>>>>> The timeout does not occur with the proposed changes. JPRT.
>>>>>>>
>>>>>>> Webrev:
>>>>>>> http://cr.openjdk.java.net/~anoll/8040798/webrev.00/
>>>>>>>
>>>>>>> Many thanks in advance,
>>>>>>> Albert
>>>>>>>
>
More information about the hotspot-compiler-dev
mailing list