RFR (S): 8003135: HotSpot inlines and hoists the Thread.currentThread().isInterrupted() out of the loop

Vladimir Ivanov vladimir.x.ivanov at oracle.com
Fri Dec 14 06:22:19 PST 2012


Pavel,

I considered adding it as a regression, but there are some problems with 
the test case [*] and I don't see an easy way to fix them.

Otherwise, it'll produce intermittent failures in our automated test 
execution.

Best regards,
Vladimir Ivanov

[*] - failure mode due to timeout, instead of explicit check
     - thread coordination is based on timing

On 12/14/12 4:07 PM, Pavel Punegov wrote:
> Vladimir,
>
> it would be great if you add code from [1] as a regression test into
> repository
>
> [1]
> http://cs.oswego.edu/pipermail/concurrency-interest/2012-November/010184.html
>
> Best regards,
>
> Pavel
>
> On Friday 14 December 2012 15:08:22 Vladimir Ivanov wrote:
>
>  >John, Vladimir K.,
>
>  >
>
>  >Here's updated version [1]
>
>  >
>
>  >Best regards,
>
>  >Vladimir Ivanov
>
>  >
>
>  >[1] http://cr.openjdk.java.net/~vlivanov/8003135/simple/webrev.01/
>
>  >
>
>  >On 12/14/12 4:11 AM, Vladimir Kozlov wrote:
>
>  >> On 12/13/12 4:55 PM, Vladimir Ivanov wrote:
>
>  >>> Vladimir K.,
>
>  >>>
>
>  >>> Thanks for the review!
>
>  >>>
>
>  >>> > You don't need second region node, use one.
>
>  >>>
>
>  >>> Can you elaborate on this a little?
>
>  >>> Do you suggest to remove slow_region node? What should I use to
> point to
>
>  >>> slow path (for example, in generate_slow_guard(bol_thr, slow_call))?
>
>  >>
>
>  >> Never mind this. We can't remove slow_region because there are 2 input
>
>  >> paths.
>
>  >>
>
>  >>> > If you rearrange code to generate slow call first and the load on
>
>  >>>
>
>  >>> fast path last you may not need to preserve init_mem.
>
>  >>
>
>  >> It looks like "fast" approach is much more complicated than I thought.
>
>  >> OK, go with "simple" case but move insert_mem_bar down (below enum)
>
>  >> where we can see it.
>
>  >>
>
>  >> Your comments for enum values are incorrect. !TLS... should be switched
>
>  >>
>
>  >> like next:
>
>  >> no_int_result_path = 1, // t == Thread.current() &&
>
>  >>
>
>  >> !TLS._osthread._interrupted
>
>  >>
>
>  >> no_clear_result_path = 2, // t == Thread.current() &&
>
>  >>
>
>  >> TLS._osthread._interrupted && !clear_int
>
>  >>
>
>  >> Thanks,
>
>  >> Vladimir K.
>
>  >>
>
>  >>> When considering moving slow path construction up, I was concerned
> about
>
>  >>>
>
>  >>> the case where there's no slow path:
>
>  >>> if (stopped()) {
>
>  >>>
>
>  >>> // There is no slow path.
>
>  >>> result_rgn->init_req(slow_result_path, top());
>
>  >>> result_val->init_req(slow_result_path, top());
>
>  >>>
>
>  >>> } else {
>
>  >>>
>
>  >>> Is it worth retaining?
>
>  >>>
>
>  >>> Best regards,
>
>  >>> Vladimir Ivanov
>
>  >>>
>
>  >>> On 12/14/12 2:05 AM, Vladimir Kozlov wrote:
>
>  >>>> John, the barrier is before enum {} in simple fix.
>
>  >>>>
>
>  >>>> But I also prefer fast code.
>
>  >>>>
>
>  >>>> Vladimir I.,
>
>  >>>>
>
>  >>>> You don't need second region node, use one.
>
>  >>>>
>
>  >>>> If you rearrange code to generate slow call first and the load on fast
>
>  >>>> path last you may not need to preserve init_mem.
>
>  >>>>
>
>  >>>> Thanks,
>
>  >>>> Vladimir K.
>
>  >>>>
>
>  >>>> On 12/13/12 2:31 PM, John Rose wrote:
>
>  >>>>> On Dec 13, 2012, at 3:02 PM, Vladimir Ivanov wrote:
>
>  >>>>>> http://cr.openjdk.java.net/~vlivanov/8003135/simple/webrev.00
>
>  >>>>>> 31 lines changed: 16 ins; 6 del; 9 mod
>
>  >>>>>>
>
>  >>>>>> In the IR produced by Thread.isInterrupted(Z)Z intrinsic it's
>
>  >>>>>> possible to hoist the load of _interrupted flag out of the loop. The
>
>  >>>>>> fix is to add a barrier to forbid such optimization.
>
>  >>>>>>
>
>  >>>>>> Proposed fix is cleaner that [1] (no explicit memory state
>
>  >>>>>> management).
>
>  >>>>>> The place for the barrier is deliberately chosen earlier than
>
>  >>>>>> necessary and it blocks hoisting of some loop invariants when
>
>  >>>>>> Thread.isInterrupted() is called in a loop. But I think it's a fair
>
>  >>>>>> price since I don't think that Thread.isInterrupted(Z)Z performance
>
>  >>>>>> in tight loops is critical.
>
>  >>>>>
>
>  >>>>> I don't see any new barrier in the simple fix. Where is it? It looks
>
>  >>>>> like the load of thr._interrupted can be hoisted under the same
>
>  >>>>> circumstances as before. If the slow path is somehow turned into a
>
>  >>>>> loop exit (via uncommon trap, maybe), then the memory state will fold
>
>  >>>>> up and the bit load can be hoisted.
>
>  >>>>>
>
>  >>>>> It seems like your "fast" fix is more robust, for this reason.
>
>  >>>>>
>
>  >>>>> Also, it's not your bug, but I'm not convinced that "slow_val =
>
>  >>>>> intcon(1)" is correct. I think another thread could come in and clear
>
>  >>>>> the interrupted bit, and this call to the native function could
> return
>
>  >>>>> false.
>
>  >>>>>
>
>  >>>>>> If you prefer [1] let me know.
>
>  >>>>>>
>
>  >>>>>> Also, cleaned up the code around a little.
>
>  >>>>>
>
>  >>>>> Good cleanups.
>
>  >>>>>
>
>  >>>>> — John
>
>  >>>>>
>
>  >>>>>> Testing: failing test, manual (verified generated code), JPRT (in
>
>  >>>>>> progress)
>
>  >>>>>>
>
>  >>>>>> Thanks!
>
>  >>>>>>
>
>  >>>>>> Best regards,
>
>  >>>>>> Vladimir Ivanov
>
>  >>>>>>
>
>  >>>>>> [1] http://cr.openjdk.java.net/~vlivanov/8003135/fast/webrev.00
>


More information about the hotspot-compiler-dev mailing list