[concurrency-interest] lazy finals - was: Here's why Atomic*FieldReference access checking is broken

Vitaly Davidovich vitalyd at gmail.com
Fri Oct 10 11:36:23 EDT 2014


Thanks for confirming.

On the subject of CHA, I think one thing I've noticed is the following.
Given the following type hierarchy and use of it:

interface Bar { void foo(); }

abstract class AbstractBar implements Bar {
      final void foo() {...}
}

final class A extends AbstractBar {}
final class B extends AbstractBar {}

class UserOfBar {
   void doFooOnBar(Bar b) {
        b.foo();
    }
}

Suppose doFooOnBar() only sees A for a while, enough times to compile the
code.  It then generates a guard checking that the receiver is A.  When B
is received, the method is deoptimized with a maybe_recompile reason (I
*think*, if I remember correctly).  Now, I think I understand why it does
that, but from a high-level standpoint, there's really no reason to deopt
because both A and B share the same impl of foo(), which is final in their
base class.  I wonder if there's any way to make the type check/guard
somehow narrow it down such that only if it sees a Bar that's not extending
AbstractBar a deopt occurs.

Is this consistent with your understanding of what would happen in the
above case?


On Fri, Oct 10, 2014 at 11:16 AM, Vladimir Ivanov <
vladimir.x.ivanov at oracle.com> wrote:

> Vitaly,
>
>      For the latter case, after the class (which violates CHA dependency)
>>     is loaded, VM guarantees there are no and won't be any running
>>     activations of affected nmethods in the system. To achieve that VM
>>     supports forcible deoptimization (and guards are an example of
>>     cooperative deoptimization) - it patches all affected activations
>>     forcing execution to continue in the interpreter.
>>
>>
>> Just to confirm, the VM loads the class and sees a dependency was
>> registered for CHA purposes that the newly loaded class violates.  The
>> ensuing patching is done under a safepoint, right?
>>
> Yes, forcible deoptimization is performed during a safepoint. Cooperative
> deoptimization doesn't trigger a safepoint - the thread hitting
> deoptimization point does all the work itself.
>
>  As an aside, classes marked final do not register any loader
>> dependencies right? (i.e. the JIT respects final on the class, even if
>> none of the non-private methods are marked final).  This is what I'd
>> expect, but just want to double-check.
>>
> Yes, there's no need to register a dependency for a method in a final
> class.
>
> Best regards,
> Vladimir Ivanov
>
>
>>     IMO, finals are closer to latter case, so once a field is changed,
>>     there should be no nmethods embedding stale value running in the
>>     system. The strategy should adapts to the application, so if an
>>     application repeatedly changes a final field and invalidates some
>>     methods, VM should leave the loads from that field as is. Current
>>     deoptimization machinery supports such scenario.
>>
>>
>> Makes sense, agree.
>>
>>     But it's just a way to optimize existing scenario. I agree with Pal
>>     that safe mechanism for the DI and serialization would be much better.
>>
>>
>> Also agree :).  It's a shame that optimizations for final fields needs
>> to jump through hoops because of DI/serialization.
>>
>> On Fri, Oct 10, 2014 at 10:48 AM, Vladimir Ivanov
>> <vladimir.x.ivanov at oracle.com <mailto:vladimir.x.ivanov at oracle.com>>
>> wrote:
>>
>>     Guards and nmethod dependencies are complementary mechanisms to
>>     track actual dependencies of the generated code. What matters is how
>>     frequent "uncommon" is: "never" (0 out of 1M), "seldom" (10s out of
>>     1M), "rare" (1000s out of 1M). Guards are always executed, so it's a
>>     good fit for checks for relatively rare conditions, but if condition
>>     is never met, it may be too much work. On the other hand,
>>     dependencies has zero overhead for common case, but deoptimization
>>     is prohibitively expensive - requires the whole VM to reach
>>     safepoint and invalidates all nmethod activations.
>>
>>     Depending on the property a dependency tracks, nmethod invalidation
>>     can be delayed or even never happen.
>>
>>     Consider 2 cases: class redefinition and CHA property invalidation.
>>
>>     In the former case, it's fine to have activations of stale versions
>>     in the system (spec allows that), but new invocations should target
>>     latest version. There's no need to invalidate existing activations.
>>
>>     For the latter case, after the class (which violates CHA dependency)
>>     is loaded, VM guarantees there are no and won't be any running
>>     activations of affected nmethods in the system. To achieve that VM
>>     supports forcible deoptimization (and guards are an example of
>>     cooperative deoptimization) - it patches all affected activations
>>     forcing execution to continue in the interpreter.
>>
>>     IMO, finals are closer to latter case, so once a field is changed,
>>     there should be no nmethods embedding stale value running in the
>>     system. The strategy should adapts to the application, so if an
>>     application repeatedly changes a final field and invalidates some
>>     methods, VM should leave the loads from that field as is. Current
>>     deoptimization machinery supports such scenario.
>>
>>     But it's just a way to optimize existing scenario. I agree with Pal
>>     that safe mechanism for the DI and serialization would be much better.
>>
>>     Best regards,
>>     Vladimir Ivanov
>>
>>     On 10/10/14, 1:30 AM, Vitaly Davidovich wrote:
>>
>>              How does Hotspot deal in general with situations where the
>>         optimized
>>              code, while executing, invalidates it's assumptions? Does
>>         this ever
>>              happen currently?
>>
>>
>>         I think this depends on the type of assumptions/optimizations
>>         made.  In
>>         some cases, a "guard" is installed, which if it doesn't pass,
>>         triggers
>>         deoptimization (i.e. generated code does some cheap check, and if
>> it
>>         doesn't pass, calls a runtime function that triggers deopt).
>> Other
>>         cases piggyback on things like class loading (e.g. devirtualizing
>>         because only one known type is loaded), and register class loading
>>         dependencies that, if triggered, will trigger deoptimization.
>>
>>         I suspect Vladimir's proposal will require another type of hook
>> that
>>         triggers when a final field is modified (so similar in principle
>> to
>>         class loading hooks).
>>
>>         On Thu, Oct 9, 2014 at 4:53 PM, Peter Levart
>>         <peter.levart at gmail.com <mailto:peter.levart at gmail.com>
>>         <mailto:peter.levart at gmail.com
>>         <mailto:peter.levart at gmail.com>__>> wrote:
>>
>>
>>              On 10/09/2014 07:53 PM, Paul Sandoz wrote:
>>
>>                  On Oct 9, 2014, at 3:23 AM, Vladimir
>>             Ivanov<vladimir.x.ivanov at __oracle.com
>>             <mailto:vladimir.x.ivanov at oracle.com>>
>>             <mailto:vladimir.x.ivanov at __oracle.com
>>
>>             <mailto:vladimir.x.ivanov at oracle.com>>  wrote:
>>
>>                      What HotSpot misses right now (to preserve
>>                 correctness w.r.t. Reflection API) is a way to track
>>                 dependencies between final fields and nmethods which
>>                 embed their values. It would allow to invalidate all
>>                 nmethods which rely on stale value and ensure the
>>                 updated value is "visible" everywhere in the running
>>                 application.
>>
>>                  In such a case would it provide a form of eventual
>>             consistency or would there be checks in place before a final
>>             field is used? e.g. one thread could be stomping on a final
>>             field while another thread is executing an nmethod under the
>>             assumption the field is final (and what if the nmethod is
>>             executing a large or infinite loop?).
>>
>>
>>              Or, if nmethod that depends on the value of the field which
>> is
>>              constant-folded in it's code, modifies this same field in
>>         1st part
>>              and after that executes 2nd part that uses constant-folded
>>         value?
>>              How does Hotspot deal in general with situations where the
>>         optimized
>>              code, while executing, invalidates it's assumptions? Does
>>         this ever
>>              happen currently?
>>
>>              Regards, Peter
>>
>>                  Instead perhaps final fields should really be final and
>>             safe mechanisms are provided to support the DI and
>>             serialization use-cases, which i suspect cover almost all
>>             use-cases.
>>
>>                  Paul.
>>
>>
>>                  _________________________________________________
>>                  Concurrency-interest mailing list
>>             Concurrency-interest at cs.__oswego.edu
>>             <mailto:Concurrency-interest at cs.oswego.edu>
>>             <mailto:Concurrency-interest at __cs.oswego.edu
>>             <mailto:Concurrency-interest at cs.oswego.edu>>
>>             http://cs.oswego.edu/mailman/__listinfo/concurrency-interest
>>             <http://cs.oswego.edu/mailman/listinfo/concurrency-interest>
>>
>>
>>
>>              _________________________________________________
>>              Concurrency-interest mailing list
>>         Concurrency-interest at cs.__oswego.edu
>>         <mailto:Concurrency-interest at cs.oswego.edu>
>>              <mailto:Concurrency-interest at __cs.oswego.edu
>>         <mailto:Concurrency-interest at cs.oswego.edu>>
>>         http://cs.oswego.edu/mailman/__listinfo/concurrency-interest
>>         <http://cs.oswego.edu/mailman/listinfo/concurrency-interest>
>>
>>
>>
>>
>>         _________________________________________________
>>         Concurrency-interest mailing list
>>         Concurrency-interest at cs.__oswego.edu
>>         <mailto:Concurrency-interest at cs.oswego.edu>
>>         http://cs.oswego.edu/mailman/__listinfo/concurrency-interest
>>         <http://cs.oswego.edu/mailman/listinfo/concurrency-interest>
>>
>>
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://cs.oswego.edu/pipermail/concurrency-interest/attachments/20141010/6043f32b/attachment.html>


More information about the Concurrency-interest mailing list