RFR(S):8151796: compiler/whitebox/BlockingCompilation.java fails due to method not compiled

Nils Eliasson nils.eliasson at oracle.com
Mon Mar 14 14:43:05 UTC 2016


Hi Volker,

On 2016-03-14 14:58, Volker Simonis wrote:
> Hi Nils,
>
> thanks for improving the test. I think your fix solves some problems 
> with regard to fast, non-blocking compiles which are wrongly 
> interpreted as blocking by the test. But what about the initial test 
> failure:
>
> java.lang.Exception: public static int BlockingCompilation.foo() 
> should be compiled at level 4(but is actually compiled at level 0)
> at BlockingCompilation.main(BlockingCompilation.java:104)
>
> This is from the loop which does blocking compilations. It seems that 
> a method enqueued for level 4 couldn't be compiled at all. I don't 
> know the exact reason, but one could be for example that the code 
> cache was full or that the compiler bailed out because of another 
> reason. I'm not sure we can accurately handle this situation in the 
> test. Maybe we should tolerate if a method couldn't be compiled at all:

This failure only happened on (slow) non-tiered platforms and the log 
looked like that as if the compiler even hadn't been put on the compile 
queue. In the first version of my rewrite I checked the return value 
from enqueueMethodForCompilation to make sure the compile was actually 
added. But then I changed my mind and focused on just testing the 
blocking functionality.

> 121 if (WB.getMethodCompilationLevel(m) != l*&& 
> **WB.getMethodCompilationLevel(m) != 0*) {
> Also, I don't understand the following code:
> 67 // Make sure no compilations can progress, blocking compiles will hang
> 68 WB.lockCompilation(); ...   78 // Normal compile on all levels
> 79 for (int l : levels) {
> 80 WB.enqueueMethodForCompilation(m, l);
>    81         }
>    82
> 83 // restore state
> 84 WB.unlockCompilation();
> 85 while (!WB.isMethodCompiled(m)) {
> 86 Thread.sleep(100);
> 87 }
> 88 WB.deoptimizeMethod(m);
>    89         WB.clearMethodState(m);
> You enqueue the methods on all levels (let's assume 1,2,3,4). Then you 
> wait until the method gets compiled at a level (lets say at level 1). 
> I think this is already shaky, because these are non-blocking compiles 
> of a method which hasn't been called before, so the requests can be 
> easily get stale.

Blocking compiles do not get stale any more - that is included in the patch.

Only one item will actually be added to the compile queue - the rest 
will be dropped because the method is already enqueued. The loop makes 
the code work on all VM-flavours (client, serverm tiered) without 
worrying about compilation levels. The compilation-lock prevents any 
compilations from completing - so the all calls on 
enqueueMethodForCompilation() will be deterministic, and most important 
- we will get a deterministic result (hanged VM) if the method is 
blocking here.

> But lets say the method will be compiled at level one. You then 
> deoptimze and clear the method state. But the queue can still contain 
> the compilation requests for the three other levels which can lead to 
> errors in the following test:

It can only get on the queue once. It looks like this in the log:

Start of test - not blocking

     524  257       1       BlockingCompilation::foo (7 bytes)
     625  257       1       BlockingCompilation::foo (7 bytes)   made not entrant

Directive added, then blocking part where all levels are tested:

  1 compiler directives added
     626  258    b  1       BlockingCompilation::foo (7 bytes)
     627  258       1       BlockingCompilation::foo (7 bytes)   made not entrant
     627  259    b  2       BlockingCompilation::foo (7 bytes)
     628  259       2       BlockingCompilation::foo (7 bytes)   made not entrant
     629  260    b  3       BlockingCompilation::foo (7 bytes)
     630  260       3       BlockingCompilation::foo (7 bytes)   made not entrant
     630  261    b  4       BlockingCompilation::foo (7 bytes)
     632  261       4       BlockingCompilation::foo (7 bytes)   made not entrant


And finally the non-blocking part where only one level gets compiled:

  633  262       1       BlockingCompilation::foo (7 bytes)


> 103 //Verify that it actuall is uncompiled
> 104 if (WB.isMethodCompiled(m)) {
> 105 throw new Exception("Should not be compiled after deoptimization");
> 106 }
> Finally some typos:
> 103 //Verify that it actuall*y* is uncompiled 111 // Add to queue 
> a*n*d make sure it actually went well
>
> Regards,
> Volker

Thanks for feedback,
Nils Eliasson

>
>
> On Mon, Mar 14, 2016 at 12:20 PM, Nils Eliasson 
> <nils.eliasson at oracle.com <mailto:nils.eliasson at oracle.com>> wrote:
>
>     Hi,
>
>     Summary:
>     The test wasn't as robust as expected.
>
>     Solution:
>     Change the way we verify that we are having a un-blocking compilation:
>     First lock the compilation queue - no new compiles will be
>     completed. Enqueue method for compilation. If the method is
>     compiled blockingly - the java thread will hang since the compile
>     can't complete as long as the compile queue is locked.
>
>     Use this to test the blocking functionality in three steps:
>     1) Verify that we are not blocking on target method as described.
>     2) Add compiler directive with instruction to block on target
>     method - verify that it can be compiled on all levels. If it is
>     not blocking it will eventually be stalled for a moment in the
>     compiler queue and the test will fail.
>     3) Pop directive, and redo step one - verify that target method is
>     not blocking.
>
>     Bug: https://bugs.openjdk.java.net/browse/JDK-8151796
>     Webrev: http://cr.openjdk.java.net/~neliasso/8151796/werev.03/
>     <http://cr.openjdk.java.net/%7Eneliasso/8151796/werev.03/>
>
>     Regards,
>     Nils Eliasson
>
>

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/hotspot-compiler-dev/attachments/20160314/7618e93e/attachment.html>


More information about the hotspot-compiler-dev mailing list