Can @Stable (or something similar) be made accessible?

classic Classic list List threaded Threaded
18 messages Options
Reply | Threaded
Open this post in threaded view
|

Can @Stable (or something similar) be made accessible?

Jason Greene
MethodHandle.invokeExact() can match the performance of direct invocation, but it requires constant folding to do so. Otherwise results are similar to Java reflection(e.g [1]).

While TrustFinalNonStaticFields can be used, it’s a sledgehammer where a scalpel is really be more appropriate.

The internal @Stable facility provides the desired semantics and precision, but it is heavily locked down, with privileged code checks and export restrictions. Could this be made more accessible (or perhaps a variant restricted to just final fields)? Informing the compiler that a final field is a true lazy initialized constant, with no store-to-final seems a pretty useful construct in general. I can understand that the long term desire is that this shouldn’t be necessary, and should be inferred [3], but at that point the annotation is still useful as documentation and legacy compatibility. If nothing else could it be allowed in non-privileged code via some flag?
It seems odd that the much more aggressive facility (TrustFinalNonStaticFields) is simpler to use than a more targeted one.

Thanks!

[1] https://www.optaplanner.org/blog/2018/01/09/JavaReflectionButMuchFaster.html
[2] http://hg.openjdk.java.net/jdk9/jdk9/jdk/file/65464a307408/src/java.base/share/classes/jdk/internal/vm/annotation/Stable.java 
[3] https://bugs.openjdk.java.net/browse/JDK-8058164
Reply | Threaded
Open this post in threaded view
|

Re: Can @Stable (or something similar) be made accessible?

aph-2
On 12/01/18 04:33, Jason Greene wrote:

> The internal @Stable facility provides the desired semantics and
> precision, but it is heavily locked down, with privileged code
> checks and export restrictions. Could this be made more accessible
> (or perhaps a variant restricted to just final fields)? Informing
> the compiler that a final field is a true lazy initialized constant,
> with no store-to-final seems a pretty useful construct in general. I
> can understand that the long term desire is that this shouldn’t be
> necessary, and should be inferred [3], but at that point the
> annotation is still useful as documentation and legacy
> compatibility. If nothing else could it be allowed in non-privileged
> code via some flag?

I don't know of any way to do that without compromising the integrity
of the JVM.  All that anybody would have to do to break the VM is to
define a field as @Stable and then change the field.  I suppose you
could say that Unsafe is just as bad and people still are allowed to
use it, but there's understandable reluctance any further to transform
a safe runtime into an unsafe one.

--
Andrew Haley
Java Platform Lead Engineer
Red Hat UK Ltd. <https://www.redhat.com>
EAC8 43EB D3EF DB98 CC77 2FAD A5CD 6035 332F A671
Reply | Threaded
Open this post in threaded view
|

Re: Can @Stable (or something similar) be made accessible?

Laurent Bourgès
Hi,

I am the author of the Marlin renderer, integrated in both java.desktop &
javafx.graphics modules.

I wonder if such core annotations @Stable @ForceInline ... could be allowed
to such openjdk modules in order to improve performance.

Marlin already uses jdk.internal.Unsafe but @Stable looks promising as
Marlin uses (and recycles) lots of int/double arrays.

I already made my fields (& constants) final but it is not enough to let
hotspot trust totally my code, isn't it ?

I think these annotations are confined to java.lang for now.
I will check thatasap.

Cheers,
Laurent

Le 12 janv. 2018 9:50 AM, "Andrew Haley" <[hidden email]> a écrit :

> On 12/01/18 04:33, Jason Greene wrote:
>
> > The internal @Stable facility provides the desired semantics and
> > precision, but it is heavily locked down, with privileged code
> > checks and export restrictions. Could this be made more accessible
> > (or perhaps a variant restricted to just final fields)? Informing
> > the compiler that a final field is a true lazy initialized constant,
> > with no store-to-final seems a pretty useful construct in general. I
> > can understand that the long term desire is that this shouldn’t be
> > necessary, and should be inferred [3], but at that point the
> > annotation is still useful as documentation and legacy
> > compatibility. If nothing else could it be allowed in non-privileged
> > code via some flag?
>
> I don't know of any way to do that without compromising the integrity
> of the JVM.  All that anybody would have to do to break the VM is to
> define a field as @Stable and then change the field.  I suppose you
> could say that Unsafe is just as bad and people still are allowed to
> use it, but there's understandable reluctance any further to transform
> a safe runtime into an unsafe one.
>
> --
> Andrew Haley
> Java Platform Lead Engineer
> Red Hat UK Ltd. <https://www.redhat.com>
> EAC8 43EB D3EF DB98 CC77 2FAD A5CD 6035 332F A671
>
Reply | Threaded
Open this post in threaded view
|

Re: Can @Stable (or something similar) be made accessible?

aph-2
On 12/01/18 09:06, Laurent Bourgès wrote:
> I already made my fields (& constants) final but it is not enough to let
> hotspot trust totally my code, isn't it ?

To some extent yes, to some extent no.  HotSpot really does trust
static final constants not to change, so @Stable won't help you
with those.  It's hard to optimize much of anything with fields
that are not static final.

--
Andrew Haley
Java Platform Lead Engineer
Red Hat UK Ltd. <https://www.redhat.com>
EAC8 43EB D3EF DB98 CC77 2FAD A5CD 6035 332F A671
Reply | Threaded
Open this post in threaded view
|

Re: Can @Stable (or something similar) be made accessible?

Aleksey Shipilev-4
In reply to this post by Jason Greene
On 01/12/2018 05:33 AM, Jason Greene wrote:
> MethodHandle.invokeExact() can match the performance of direct invocation, but it requires
> constant folding to do so. Otherwise results are similar to Java reflection(e.g [1]).
>
> While TrustFinalNonStaticFields can be used, it’s a sledgehammer where a scalpel is really be
> more appropriate.

So, the easier way out would be enable TrustFinalNonStaticFields to be used with finer-grained
control, that JEP 165 (Compiler Control) provides. Then you can tell which user-side
classes/packages are safe for trusting, and which are not. IIRC, the reason why
TrustFinalNonStaticFields is not on by default is because we cannot rely that everyone is not
writing to final fields and expecting update to be visible.

...which makes this one partially go away:

> It seems odd that the much more aggressive facility (TrustFinalNonStaticFields) is simpler to
> use than a more targeted one.
Thanks,
-Aleksey

Reply | Threaded
Open this post in threaded view
|

Re: Can @Stable (or something similar) be made accessible?

Peter Levart
In reply to this post by aph-2
Hi Andrew,

On 01/12/2018 09:47 AM, Andrew Haley wrote:

> On 12/01/18 04:33, Jason Greene wrote:
>
>> The internal @Stable facility provides the desired semantics and
>> precision, but it is heavily locked down, with privileged code
>> checks and export restrictions. Could this be made more accessible
>> (or perhaps a variant restricted to just final fields)? Informing
>> the compiler that a final field is a true lazy initialized constant,
>> with no store-to-final seems a pretty useful construct in general. I
>> can understand that the long term desire is that this shouldn’t be
>> necessary, and should be inferred [3], but at that point the
>> annotation is still useful as documentation and legacy
>> compatibility. If nothing else could it be allowed in non-privileged
>> code via some flag?
> I don't know of any way to do that without compromising the integrity
> of the JVM.  All that anybody would have to do to break the VM is to
> define a field as @Stable and then change the field.

Would you be so kind to explain how this breakage occurs? I can
understand that improper use of @Stable annotation may break the
intended semantics of a program, but to break the integrity of VM? I'm
trying to imagine the scenario, but can't.

Regards, Peter

Reply | Threaded
Open this post in threaded view
|

Re: Can @Stable (or something similar) be made accessible?

Vitaly Davidovich
On Fri, Jan 12, 2018 at 6:36 AM Peter Levart <[hidden email]> wrote:

> Hi Andrew,
>
> On 01/12/2018 09:47 AM, Andrew Haley wrote:
> > On 12/01/18 04:33, Jason Greene wrote:
> >
> >> The internal @Stable facility provides the desired semantics and
> >> precision, but it is heavily locked down, with privileged code
> >> checks and export restrictions. Could this be made more accessible
> >> (or perhaps a variant restricted to just final fields)? Informing
> >> the compiler that a final field is a true lazy initialized constant,
> >> with no store-to-final seems a pretty useful construct in general. I
> >> can understand that the long term desire is that this shouldn’t be
> >> necessary, and should be inferred [3], but at that point the
> >> annotation is still useful as documentation and legacy
> >> compatibility. If nothing else could it be allowed in non-privileged
> >> code via some flag?
> > I don't know of any way to do that without compromising the integrity
> > of the JVM.  All that anybody would have to do to break the VM is to
> > define a field as @Stable and then change the field.
>
> Would you be so kind to explain how this breakage occurs? I can
> understand that improper use of @Stable annotation may break the
> intended semantics of a program, but to break the integrity of VM? I'm
> trying to imagine the scenario, but can't.

One example might be a @Stable array field used with a constant index to
write a value into it.  If the JIT trusts the field to be final it could
elide a range check when storing into the slot.  If the field is actually
modified to be a smaller length array, you’d end up with a write to an out
of bounds memory area.

I suppose something similar can be done with a non-array field - make the
field type Object, store a Foo initially.  The JIT can assume the type is
always Foo and generate read/writes using its layout.  Then change the
field to another type.

>
>
> Regards, Peter
>
> --
Sent from my phone
Reply | Threaded
Open this post in threaded view
|

Re: Can @Stable (or something similar) be made accessible?

Peter Levart


On 01/12/2018 01:11 PM, Vitaly Davidovich wrote:

> On Fri, Jan 12, 2018 at 6:36 AM Peter Levart <[hidden email]> wrote:
>
>> Hi Andrew,
>>
>> On 01/12/2018 09:47 AM, Andrew Haley wrote:
>>> On 12/01/18 04:33, Jason Greene wrote:
>>>
>>>> The internal @Stable facility provides the desired semantics and
>>>> precision, but it is heavily locked down, with privileged code
>>>> checks and export restrictions. Could this be made more accessible
>>>> (or perhaps a variant restricted to just final fields)? Informing
>>>> the compiler that a final field is a true lazy initialized constant,
>>>> with no store-to-final seems a pretty useful construct in general. I
>>>> can understand that the long term desire is that this shouldn’t be
>>>> necessary, and should be inferred [3], but at that point the
>>>> annotation is still useful as documentation and legacy
>>>> compatibility. If nothing else could it be allowed in non-privileged
>>>> code via some flag?
>>> I don't know of any way to do that without compromising the integrity
>>> of the JVM.  All that anybody would have to do to break the VM is to
>>> define a field as @Stable and then change the field.
>> Would you be so kind to explain how this breakage occurs? I can
>> understand that improper use of @Stable annotation may break the
>> intended semantics of a program, but to break the integrity of VM? I'm
>> trying to imagine the scenario, but can't.
> One example might be a @Stable array field used with a constant index to
> write a value into it.  If the JIT trusts the field to be final it could
> elide a range check when storing into the slot.  If the field is actually
> modified to be a smaller length array, you’d end up with a write to an out
> of bounds memory area.
>
> I suppose something similar can be done with a non-array field - make the
> field type Object, store a Foo initially.  The JIT can assume the type is
> always Foo and generate read/writes using its layout.  Then change the
> field to another type.

So you are saying that JIT might optimize some aspects of code assuming
the "constantness" of the value of the field (for example inline code
for a particular type of object or skip index range check), but not
optimize other aspects - for example still read the value of the field
from the field's primary location in containing object to obtain 'this'
pointer or index value. Is this really they way JIT does
compilation/optimization? I would assume that if JIT optimizes code
assuming some value is constant, it also uses this same constant value
in the optimized code and not emit code that actually reads the value
from the primary field location or assume that that value already
resides in some register which was established in non-optimized part of
code. I'm probably wrong in assuming that.

So one that uses @Stable annotation on fields in JDK internals must be
very careful not to break the rules which are very subtle or he may
create situations that compromise stability of VM? There are places in
JDK using @Stable annotations where such marked fields can be written to
more than once with different values (racy caching). Are you saying that
all those values that are written to a @Stable field must be equivalent
not only in terms of Java logic but in case they are reference values,
they must also point to the object of the same runtime class or else the
stability of VM may be compromised?

Thanks,

Peter


>
>>
>> Regards, Peter
>>
>> --
> Sent from my phone
>

Reply | Threaded
Open this post in threaded view
|

Re: Can @Stable (or something similar) be made accessible?

Vladimir Ivanov
In reply to this post by Vitaly Davidovich
>> Would you be so kind to explain how this breakage occurs? I can
>> understand that improper use of @Stable annotation may break the
>> intended semantics of a program, but to break the integrity of VM? I'm
>> trying to imagine the scenario, but can't.
>
> One example might be a @Stable array field used with a constant index to
> write a value into it.  If the JIT trusts the field to be final it could
> elide a range check when storing into the slot.  If the field is actually
> modified to be a smaller length array, you’d end up with a write to an out
> of bounds memory area.
>
> I suppose something similar can be done with a non-array field - make the
> field type Object, store a Foo initially.  The JIT can assume the type is
> always Foo and generate read/writes using its layout.  Then change the
> field to another type.

No, it doesn't work that way. @Stable enables JIT to constant fold loads
from fields/arrays (holding non-default values) whenever possible. After
that JIT has a constant value at its hands. All other optimizations
follows from that: range check before array store can be elided since
array instance is known and its length is known as well, type check can
be elided since constant type is known. But the value won't be reloaded
from memory, all optimizations happen on a constant which was loaded
from memory once during compilation.

So, the worst case scenario is: a value written into @Stable field/array
  is never visible in some code no matter what you do. It can lead to
nasty bugs when different parts of program don't agree on observed
value. It can happen when user doesn't obey @Stable contract and
performs multiple writes into a @Stable field/array. Current
implementation in HotSpot doesn't forbid that.

Best regards,
Vladimir Ivanov
Reply | Threaded
Open this post in threaded view
|

Re: Can @Stable (or something similar) be made accessible?

Vitaly Davidovich
On Fri, Jan 12, 2018 at 7:50 AM, Vladimir Ivanov <
[hidden email]> wrote:

> Would you be so kind to explain how this breakage occurs? I can
>>> understand that improper use of @Stable annotation may break the
>>> intended semantics of a program, but to break the integrity of VM? I'm
>>> trying to imagine the scenario, but can't.
>>>
>>
>> One example might be a @Stable array field used with a constant index to
>> write a value into it.  If the JIT trusts the field to be final it could
>> elide a range check when storing into the slot.  If the field is actually
>> modified to be a smaller length array, you’d end up with a write to an out
>> of bounds memory area.
>>
>> I suppose something similar can be done with a non-array field - make the
>> field type Object, store a Foo initially.  The JIT can assume the type is
>> always Foo and generate read/writes using its layout.  Then change the
>> field to another type.
>>
>
> No, it doesn't work that way. @Stable enables JIT to constant fold loads
> from fields/arrays (holding non-default values) whenever possible. After
> that JIT has a constant value at its hands. All other optimizations follows
> from that: range check before array store can be elided since array
> instance is known and its length is known as well, type check can be elided
> since constant type is known. But the value won't be reloaded from memory,
> all optimizations happen on a constant which was loaded from memory once
> during compilation.
>
> So, the worst case scenario is: a value written into @Stable field/array
> is never visible in some code no matter what you do. It can lead to nasty
> bugs when different parts of program don't agree on observed value. It can
> happen when user doesn't obey @Stable contract and performs multiple writes
> into a @Stable field/array. Current implementation in HotSpot doesn't
> forbid that.
>
Thanks for clarifying Vladimir - that makes sense.  So back to the
integrity of the VM question - what can be compromised then? I suppose if
one was to use Unsafe access in combination with relying on a @Stable field
to feed it info (e.g. index into some memory accessed via Unsafe), then
things can go south.  But Unsafe is already, well, unsafe.  What extra VM
integrity issues would a misbehaving @Stable cause that Andrew was alluding
to?

>
> Best regards,
> Vladimir Ivanov
>
Reply | Threaded
Open this post in threaded view
|

Re: Can @Stable (or something similar) be made accessible?

Jason Greene
In reply to this post by Vladimir Ivanov

> On Jan 12, 2018, at 6:50 AM, Vladimir Ivanov <[hidden email]> wrote:
>

-snip-

> So, the worst case scenario is: a value written into @Stable field/array  is never visible in some code no matter what you do. It can lead to nasty bugs when different parts of program don't agree on observed value. It can happen when user doesn't obey @Stable contract and performs multiple writes into a @Stable field/array. Current implementation in HotSpot doesn’t
> forbid that.
>


This isn’t much different from the already allowed fine tuning of memory model effects (e.g., observing stale values from a plain write). In those scenarios, as is the case with @Stable, developers have to be aware of and honor the respective contract. It could be argued that bugs arising from contract violations of @Stable are easier to catch, due to their persistent nature.

-Jason
Reply | Threaded
Open this post in threaded view
|

Re: Can @Stable (or something similar) be made accessible?

Vitaly Davidovich
On Fri, Jan 12, 2018 at 11:28 AM Jason Greene <[hidden email]>
wrote:

>
> > On Jan 12, 2018, at 6:50 AM, Vladimir Ivanov <
> [hidden email]> wrote:
> >
>
> -snip-
>
> > So, the worst case scenario is: a value written into @Stable
> field/array  is never visible in some code no matter what you do. It can
> lead to nasty bugs when different parts of program don't agree on observed
> value. It can happen when user doesn't obey @Stable contract and performs
> multiple writes into a @Stable field/array. Current implementation in
> HotSpot doesn’t
> > forbid that.
> >
>
>
> This isn’t much different from the already allowed fine tuning of memory
> model effects (e.g., observing stale values from a plain write). In those
> scenarios, as is the case with @Stable, developers have to be aware of and
> honor the respective contract. It could be argued that bugs arising from
> contract violations of @Stable are easier to catch, due to their persistent
> nature.

Theyre only sort of persistent - they’re persistent only after the code is
JIT’d and also stays JIT’d (ie no deopt back to interpreter).  But JIT
itself is non-deterministic so it could create some really funky behavior,
and maybe even heisenbugs.

>
>
> -Jason

--
Sent from my phone
Reply | Threaded
Open this post in threaded view
|

Re: Can @Stable (or something similar) be made accessible?

Remi Forax
In reply to this post by Aleksey Shipilev-4
Or you can use method handles ...

I've not tested but this should work:
https://gist.github.com/forax/e49d63d50e5973f602f720ba3b6ea1b8

I have implemented two semantics, either do a call to get field value the first time (FIRST_WIN) and then for the subsequent calls always return this value as a constant or put a guard (if) that checks that the reference never change so instead of getting the field value, i always return the same constant (STABLE).

You may think that it doesn't work because the method handle is a captured value of a lambda that is stored in a field of the lambda proxy but the VM has a special case for that (fields of VM anonynous classes (as the lambda proxies) are always trusted, see [1]). So it's safe, from the perf POV to use lambdas has a mechanism to hidden the method handle incantations.

cheers,
Rémi

[1] https://shipilev.net/jvm-anatomy-park/17-trust-nonstatic-final-fields/

----- Mail original -----
> De: "Aleksey Shipilev" <[hidden email]>
> À: "Jason Greene" <[hidden email]>, "core-libs-dev" <[hidden email]>
> Envoyé: Vendredi 12 Janvier 2018 11:37:37
> Objet: Re: Can @Stable (or something similar) be made accessible?

> On 01/12/2018 05:33 AM, Jason Greene wrote:
>> MethodHandle.invokeExact() can match the performance of direct invocation, but
>> it requires
>> constant folding to do so. Otherwise results are similar to Java reflection(e.g
>> [1]).
>>
>> While TrustFinalNonStaticFields can be used, it’s a sledgehammer where a scalpel
>> is really be
>> more appropriate.
>
> So, the easier way out would be enable TrustFinalNonStaticFields to be used with
> finer-grained
> control, that JEP 165 (Compiler Control) provides. Then you can tell which
> user-side
> classes/packages are safe for trusting, and which are not. IIRC, the reason why
> TrustFinalNonStaticFields is not on by default is because we cannot rely that
> everyone is not
> writing to final fields and expecting update to be visible.
>
> ...which makes this one partially go away:
>
>> It seems odd that the much more aggressive facility (TrustFinalNonStaticFields)
>> is simpler to
>> use than a more targeted one.
> Thanks,
> -Aleksey
Reply | Threaded
Open this post in threaded view
|

Re: Can @Stable (or something similar) be made accessible?

Vladimir Ivanov
In reply to this post by Jason Greene

> This isn’t much different from the already allowed fine tuning of memory model effects (e.g., observing stale values from a plain write). In those scenarios, as is the case with @Stable, developers have to be aware of and honor the respective contract. It could be argued that bugs arising from contract violations of @Stable are easier to catch, due to their persistent nature.

The crucial difference is that @Stable doesn't obey JMM while others do
(though you can break that as well using Unsafe or Reflection API), so
all the tricks programmers rely on (locks, finals, volatiles, fences)
don't work.

Considering the contract is not enforced at runtime (in current
implementation), it's easy to violate it (especially with concurrent
accesses).

And, as practice shows, it's very hard to track down bugs causing change
in behavior between different execution modes (interpreter vs compiled
code vs recompiled code).

To sum it up, standardizing something which increases complexity of the
area which is already quite complicated (JMM) doesn't look like a wise
move in a long term.

Best regards,
Vladimir Ivanov
Reply | Threaded
Open this post in threaded view
|

Re: Can @Stable (or something similar) be made accessible?

Vladimir Ivanov
In reply to this post by Vitaly Davidovich
>
>     No, it doesn't work that way. @Stable enables JIT to constant fold
>     loads from fields/arrays (holding non-default values) whenever
>     possible. After that JIT has a constant value at its hands. All
>     other optimizations follows from that: range check before array
>     store can be elided since array instance is known and its length is
>     known as well, type check can be elided since constant type is
>     known. But the value won't be reloaded from memory, all
>     optimizations happen on a constant which was loaded from memory once
>     during compilation.
>
>     So, the worst case scenario is: a value written into @Stable
>     field/array  is never visible in some code no matter what you do. It
>     can lead to nasty bugs when different parts of program don't agree
>     on observed value. It can happen when user doesn't obey @Stable
>     contract and performs multiple writes into a @Stable field/array.
>     Current implementation in HotSpot doesn't forbid that.
>
> Thanks for clarifying Vladimir - that makes sense.  So back to the
> integrity of the VM question - what can be compromised then? I suppose
> if one was to use Unsafe access in combination with relying on a @Stable
> field to feed it info (e.g. index into some memory accessed via Unsafe),
> then things can go south.  But Unsafe is already, well, unsafe.  What
> extra VM integrity issues would a misbehaving @Stable cause that Andrew
> was alluding to?

I don't know what exactly Andrew had in mind.

Though misuse of @Stable can't be a direct cause of JVM crashes, it can
lead to serious bugs in user code which manifest themselves as
JIT-compiler bugs. And miscompiled code silently corrupting user data is
usually considered much more serious issue than a JVM crash.

Best regards,
Vladimir Ivanov
Reply | Threaded
Open this post in threaded view
|

Re: Can @Stable (or something similar) be made accessible?

Vladimir Ivanov
In reply to this post by Jason Greene
Jason,

I wouldn't consider @Stable as a scalpel :-)

It's heavily locked down for a reason: it wasn't designed for eventual
standardization, but as (1) an experiment in _multiple_ directions; and
(2) solution for immediate problems in java.lang.invoke.

@Stable mixes (incomplete implementations of) 2 independent features
(lazy initialization of finals + constant arrays), while trusting
instance finals is just a consequence of locking it down to privileged
code (JIT-compilers already trust final instance fields in different
core packages).

Current implementation doesn't enforce at runtime the contract and
allows multiple writes to @Stable field. It is useful in rare cases, but
overall significantly complicates proper usage of @Stable.

All those factors make @Stable unfit for public exposure in it's current
form.

Both referenced features are independently explored (as lazy finals and
frozen arrays).

Also, @Stable is not a substitute for final fields: default value is
treated specially (not optimized), while "final" covers the whole range
of values of a type.

For optimizing final fields there are much more promising approaches:

   (1) optimistic optimizations in JITs: treat finals as constants and
track updates invalidating code which relies on that (there were some
experiments, e.g. [1]);

   (2) forbid final field updates at runtime after initialization is
over and freely optimize them in JITs.

Both approaches still have some roadblocks on their way (deserialization
relies on modifying final fields, hard to track final field values of
individual objects in JVM, etc), but the platform steadily moves in the
direction of treating final fields as truly final by default.

Best regards,
Vladimir Ivanov

[1]
http://mail.openjdk.java.net/pipermail/hotspot-compiler-dev/2015-June/018342.html

On 1/12/18 7:33 AM, Jason Greene wrote:

> MethodHandle.invokeExact() can match the performance of direct invocation, but it requires constant folding to do so. Otherwise results are similar to Java reflection(e.g [1]).
>
> While TrustFinalNonStaticFields can be used, it’s a sledgehammer where a scalpel is really be more appropriate.
>
> The internal @Stable facility provides the desired semantics and precision, but it is heavily locked down, with privileged code checks and export restrictions. Could this be made more accessible (or perhaps a variant restricted to just final fields)? Informing the compiler that a final field is a true lazy initialized constant, with no store-to-final seems a pretty useful construct in general. I can understand that the long term desire is that this shouldn’t be necessary, and should be inferred [3], but at that point the annotation is still useful as documentation and legacy compatibility. If nothing else could it be allowed in non-privileged code via some flag?
> It seems odd that the much more aggressive facility (TrustFinalNonStaticFields) is simpler to use than a more targeted one.
>
> Thanks!
>
> [1] https://www.optaplanner.org/blog/2018/01/09/JavaReflectionButMuchFaster.html
> [2] http://hg.openjdk.java.net/jdk9/jdk9/jdk/file/65464a307408/src/java.base/share/classes/jdk/internal/vm/annotation/Stable.java
> [3] https://bugs.openjdk.java.net/browse/JDK-8058164
>
Reply | Threaded
Open this post in threaded view
|

Re: Can @Stable (or something similar) be made accessible?

Jason Greene

> On Jan 15, 2018, at 6:51 AM, Vladimir Ivanov <[hidden email]> wrote:
>
> Jason,
>
> I wouldn't consider @Stable as a scalpel :-)
>
> It's heavily locked down for a reason: it wasn't designed for eventual standardization, but as (1) an experiment in _multiple_ directions; and (2) solution for immediate problems in java.lang.invoke.
>
> @Stable mixes (incomplete implementations of) 2 independent features (lazy initialization of finals + constant arrays), while trusting instance finals is just a consequence of locking it down to privileged code (JIT-compilers already trust final instance fields in different core packages).
>
> Current implementation doesn't enforce at runtime the contract and allows multiple writes to @Stable field. It is useful in rare cases, but overall significantly complicates proper usage of @Stable.
>
> All those factors make @Stable unfit for public exposure in it’s current form.
>
> Both referenced features are independently explored (as lazy finals and frozen arrays).
>
> Also, @Stable is not a substitute for final fields: default value is treated specially (not optimized), while "final" covers the whole range of values of a type.
>
> For optimizing final fields there are much more promising approaches:
>
>  (1) optimistic optimizations in JITs: treat finals as constants and track updates invalidating code which relies on that (there were some experiments, e.g. [1]);
>
>  (2) forbid final field updates at runtime after initialization is over and freely optimize them in JITs.
>
> Both approaches still have some roadblocks on their way (deserialization relies on modifying final fields, hard to track final field values of individual objects in JVM, etc), but the platform steadily moves in the direction of treating final fields as truly final by default.

Thanks for the explanation Vladimir,

I can certainly understand optimistic optimization being the end goal, but, correct me if I am wrong, it seems an improvement in the distant future. I can see the issue is scheduled for 11, but I imagine that is more of a placeholder.  

Has a narrow variant of (2) in the same vein as @Stable been considered, as it seems to overcome the roadblocks mentioned? An annotation placed on a final field (something like @Constant, @StrictFinal, @ImmutableAfterPublish, whatever) could indicate opting in to the contract of this field as a truly final field, freeing the JVM to optimize and validate as desired (e.g. special case serialization, preventing setAcessible/JNI set field/VarHandle/etc), and without introducing compatibility issues. I realize validating access via Unsafe is non-trivial, but I argue there is limited value in doing so, since the effects are not worse than other actions one might take with Unsafe. Further, I argue any validation at all is going above and beyond, as “undefined” is a perfectly reasonable result for contract violations.

-Jason
Reply | Threaded
Open this post in threaded view
|

Re: Can @Stable (or something similar) be made accessible?

Jason Greene
In reply to this post by Vladimir Ivanov

> On Jan 15, 2018, at 6:00 AM, Vladimir Ivanov <[hidden email]> wrote:
>
>
>> This isn’t much different from the already allowed fine tuning of memory model effects (e.g., observing stale values from a plain write). In those scenarios, as is the case with @Stable, developers have to be aware of and honor the respective contract. It could be argued that bugs arising from contract violations of @Stable are easier to catch, due to their persistent nature.
>
> The crucial difference is that @Stable doesn’t obey JMM while others do (though you can break that as well using Unsafe or Reflection API), so all the tricks programmers rely on (locks, finals, volatiles, fences) don't work.

Right and also VarHandle and AtomicReferenceFieldUpdater, which let you weaken the effect of a write, such that stale reads on the reading side may occur.

-Jason