[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