<p dir="ltr">Vladimir,</p>
<p dir="ltr">Nice to hear you guys are looking to do something about this.  Supposing there was a way to track nmethod dependencies on final fields (with invalidation upon change), presumably this mechanism could be extended to track non-final arrays as well and thus support the examples Paul brought up?</p>
<p dir="ltr">Sent from my phone</p>
<div class="gmail_quote">On Sep 10, 2014 9:36 AM, "Vladimir Ivanov" <<a href="mailto:vladimir.x.ivanov@oracle.com">vladimir.x.ivanov@oracle.com</a>> wrote:<br type="attribution"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Remi,<br>
<br>
@Stable isn't a full match for final field case, since it doesn't treat default values as constants. But I agree, it's close.<br>
<br>
Hotspot already constant folds loads from static final fields and there's an experimental flag TrustFinalNonStaticFields for final instance fields.<br>
<br>
What we miss right now for preserving correctness w.r.t. Reflection API is a way to track dependencies between final fields and nmethods and invalidate all nmethods which (possibly) embed changed final values.<br>
<br>
Best regards,<br>
Vladimir Ivanov<br>
<br>
On 9/10/14, 5:04 PM, Remi Forax wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
On 09/10/2014 02:41 PM, Vitaly Davidovich wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
I think there's a fundamental problem in trying to "convey" things to<br>
the compiler.  Clearly, it can't be some metadata approach since<br>
compiler can't just trust user blindly. The only way I know to convey<br>
things is through code shape.<br>
<br>
One thing that bothers me is that even fields marked final aren't<br>
really treated as such by compiler because it's paranoid of things<br>
like reflection.<br>
<br>
</blockquote>
<br>
It's not paranoid, most of the dependency injection libraries, Hibernate<br>
or serialization code allow you to set the value of final field at runtime.<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
If there was some way to reassure it that final fields aren't modified<br>
behind its back, then more type info can be captured at init time<br>
(e.g. array is not null and length is captured as a constant).<br>
<br>
</blockquote>
<br>
@java.lang.invoke.Stable<br>
<br>
Rémi<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Sent from my phone<br>
<br>
On Sep 10, 2014 6:48 AM, "Paul Sandoz" <<a href="mailto:paul.sandoz@oracle.com" target="_blank">paul.sandoz@oracle.com</a><br>
<mailto:<a href="mailto:paul.sandoz@oracle.com" target="_blank">paul.sandoz@oracle.com</a><u></u>>> wrote:<br>
<br>
    Hi,<br>
<br>
    This method:<br>
<br>
        static int aaload(int[] a, int i) {<br>
            int index = i & (a.length - 1);<br>
<br>
            return a[index];<br>
        }<br>
<br>
    compiles to:<br>
<br>
      0x000000010466a56c: mov    0xc(%rsi),%r11d    ;*arraylength<br>
                                                    ; implicit<br>
    exception: dispatches to 0x000000010466a5a5<br>
      0x000000010466a570: mov    %r11d,%r10d<br>
      0x000000010466a573: dec    %r10d<br>
      0x000000010466a576: and    %r10d,%edx         ;*iand<br>
<br>
      0x000000010466a579: cmp    %r11d,%edx<br>
      0x000000010466a57c: jae    0x000000010466a58e<br>
      0x000000010466a57e: mov    0x10(%rsi,%rdx,4),%eax<br>
<br>
<br>
    For the bounds check there is only one unsigned comparison check<br>
    since the array length is non-negative (this will also catch the<br>
    case if "i" is -ve and the array length is 0).<br>
<br>
    If the patch for JDK-8003585 is applied the check gets strength<br>
    reduced to:<br>
<br>
      0x000000010d9e06ec: mov    0xc(%rsi),%r11d    ;*arraylength<br>
                                                    ; implicit<br>
    exception: dispatches to 0x000000010d9e0725<br>
      0x000000010d9e06f0: mov    %r11d,%r10d<br>
      0x000000010d9e06f3: dec    %r10d<br>
      0x000000010d9e06f6: and    %r10d,%edx         ;*iand<br>
<br>
      0x000000010d9e06f9: test   %r11d,%r11d<br>
      0x000000010d9e06fc: jbe    0x000000010d9e070e<br>
      0x000000010d9e06fe: mov    0x10(%rsi,%rdx,4),%eax<br>
<br>
    and if the array is constant or there is a dominating check<br>
    (hoisted out of a loop) then the bounds check will go away. More<br>
    on that later.<br>
<br>
<br>
    This method:<br>
<br>
        int unsafe_aaload(int[] a, int i) {<br>
            int index = i & (a.length - 1);<br>
<br>
            // Emulate return a[index]<br>
            if (index < 0 || index >= a.length)<br>
                throw new ArrayIndexOutOfBoundsException<u></u>();<br>
<br>
            long address = (((long) index) << 2) +<br>
    UNSAFE.ARRAY_INT_BASE_OFFSET;<br>
            return UNSAFE.getInt(a, address);<br>
        }<br>
<br>
    compiles to:<br>
<br>
      0x000000010495be8c: mov    0xc(%rdx),%r10d    ;*arraylength<br>
                                                    ; implicit<br>
    exception: dispatches to 0x000000010495bee9<br>
      0x000000010495be90: mov    %r10d,%r8d<br>
      0x000000010495be93: dec    %r8d<br>
      0x000000010495be96: and    %r8d,%ecx          ;*iand<br>
<br>
      0x000000010495be99: test   %ecx,%ecx<br>
      0x000000010495be9b: jl     0x000000010495beb6  ;*iflt<br>
<br>
      0x000000010495be9d: cmp    %r10d,%ecx<br>
      0x000000010495bea0: jge    0x000000010495becd  ;*if_icmplt<br>
<br>
      0x000000010495bea2: movslq %ecx,%r10<br>
      0x000000010495bea5: mov    0x10(%rdx,%r10,4),%eax<br>
    ;*invokevirtual getInt<br>
<br>
<br>
    The patch for JDK-8003585 makes no difference.<br>
<br>
    (Note: in general we cannot assume that "int index = i & (a.length<br>
    - 1)" always occurs before the bounds checks, otherwise i would<br>
    have explicitly written "if (a.length == 0) throw ...")<br>
<br>
    Ideally similar code as shown for an aaload should be generated.<br>
    Any suggestions/ideas on how to make that happen?<br>
<br>
<br>
    --<br>
<br>
    Regarding removing the bounds checks, as previously referred to.<br>
    If it is known the array length is always > 0 the bounds check can<br>
    be removed. The general context here is code in the<br>
    ForkJoinPool.WorkQueue, such as:<br>
<br>
            final ForkJoinTask<?> poll() {<br>
                ForkJoinTask<?>[] a; int b; ForkJoinTask<?> t;<br>
                while ((b = base) - top < 0 && (a = array) != null) {<br>
                    int j = (((a.length - 1) & b) << ASHIFT) + ABASE;<br>
                    t = (ForkJoinTask<?>)U.<u></u>getObjectVolatile(a, j);<br>
                    if (base == b) {<br>
                        if (t != null) {<br>
                            if (U.compareAndSwapObject(a, j, t, null)) {<br>
                                base = b + 1;<br>
                                return t;<br>
                            }<br>
                        }<br>
                        else if (b + 1 == top) // now empty<br>
                            break;<br>
                    }<br>
                }<br>
                return null;<br>
            }<br>
<br>
    If "array" is not null it's length is always > 0 (a zero length<br>
    array is never allocated by the code). Is there a way to safely<br>
    convey that knowledge to the runtime/compiler? thereby enabling<br>
    removal of bounds checks for any replacement of Unsafe in such code.<br>
<br>
    Paul.<br>
<br>
</blockquote>
<br>
</blockquote>
</blockquote></div>