From maurizio.cimadamore at oracle.com Tue Sep 2 13:23:52 2014 From: maurizio.cimadamore at oracle.com (maurizio.cimadamore at oracle.com) Date: Tue, 02 Sep 2014 13:23:52 +0000 Subject: hg: valhalla/valhalla/langtools: Refine support for specialized generic methods Message-ID: <201409021323.s82DNrUi011518@aojmv0008> Changeset: 5f89597744f1 Author: mcimadamore Date: 2014-09-02 14:23 +0100 URL: http://hg.openjdk.java.net/valhalla/valhalla/langtools/rev/5f89597744f1 Refine support for specialized generic methods * BytecodeMapping for invokedynamic now mentions fully instantiated method type * BytecodeMapping now generated in all cases of specialized generic method call * Refine definition of specialized generic method call to include 'any' tvars instantiations * Add more tests Todo: Fully instantiated generic method types is needed even if call is not 'specialized', as that can be useful to keep propagating unerased types and generate further BytecodeMapping attrs. ! src/jdk.compiler/share/classes/com/sun/tools/javac/comp/SpecializeTypes.java ! src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Items.java ! src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java ! test/tools/javac/valhalla/typespec/items/tests/TestIndy.java + test/tools/javac/valhalla/typespec/items/tests/TestIndyFactory.java From maurizio.cimadamore at oracle.com Tue Sep 2 16:36:52 2014 From: maurizio.cimadamore at oracle.com (maurizio.cimadamore at oracle.com) Date: Tue, 02 Sep 2014 16:36:52 +0000 Subject: hg: valhalla/valhalla/langtools: Add support for BytecodeMapping attribute in compiler-generated cast expressions Message-ID: <201409021636.s82GardY013817@aojmv0008> Changeset: 0c2032680967 Author: mcimadamore Date: 2014-09-02 17:36 +0100 URL: http://hg.openjdk.java.net/valhalla/valhalla/langtools/rev/0c2032680967 Add support for BytecodeMapping attribute in compiler-generated cast expressions ! src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java ! test/tools/javac/valhalla/typespec/items/tests/TestNestedGenerics.java + test/tools/javac/valhalla/typespec/items/tests/TestSyntheticCast.java From paul.sandoz at oracle.com Tue Sep 2 16:41:06 2014 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Tue, 2 Sep 2014 18:41:06 +0200 Subject: FTR: JVM Lang Summit presentation In-Reply-To: <1FC8A755-3C36-4B5C-84AE-5A080ADBE926@oracle.com> References: <4ADC415B-CD55-402A-AC3E-AC8A6C0535BA@oracle.com> <53E0F9DA.3030308@univ-mlv.fr> <1FC8A755-3C36-4B5C-84AE-5A080ADBE926@oracle.com> Message-ID: <54AF20F9-193D-4807-946A-4E9C523A2C98@oracle.com> On Aug 8, 2014, at 3:01 AM, John Rose wrote: > > But for now we are learning the most, the fastest, by using the VarHandle prototype. > [Finally getting back on track after vacation...] Yes, the current prototype is the minimal cut of code i could write to get up and running. One can think of it as indy-in-spirit but leveraging the lower-level method invocation mechanisms. I hope the results of investigations will also be applicable to DHMs and/or an indy-based solution. It deliberately avoids use of LFs because at the time i was not sure how the LF code was gonna evolve and i also wanted an initial solution that performed no anon class spinning (minimizes warm up and is also easy to debug). My experience so far, having converted over j.u.concurrent classes from Unsafe, is the VarHandle API is reasonable, on a par or marginally better than Unsafe usage (and of course safe). Experimental improvements to that API are possible with FieldHandle and ArrayHandle, but they use a devious trick to avoid boxing which is probably going too far (in the absence of using "any" and dependencies on post-9 features). On a brief look the "signature polymorphic" term within the JLS and JVMS specs is referred to sparingly. It may not be so tricky to update to refer to another class with polysig methods, but i can understand why it may not be satisfying to make such hard-coded updates. At the moment my gut-feeling is VarHandle might be a suitable replacement, within the Java 9 time-frame, of Unsafe use in many j.u.c. classes. But, i think we should keep hammering on this with regards to how hotspot optimizes and what we learn as specialization/value types progresses. Paul. From paul.sandoz at oracle.com Tue Sep 2 16:59:44 2014 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Tue, 2 Sep 2014 18:59:44 +0200 Subject: FTR: JVM Lang Summit presentation In-Reply-To: <53E54267.4030505@univ-mlv.fr> References: <4ADC415B-CD55-402A-AC3E-AC8A6C0535BA@oracle.com> <53E0F9DA.3030308@univ-mlv.fr> <1FC8A755-3C36-4B5C-84AE-5A080ADBE926@oracle.com> <53E54267.4030505@univ-mlv.fr> Message-ID: <7884990C-E602-4339-A557-1FDB98FBD3F7@oracle.com> On Aug 8, 2014, at 11:34 PM, Remi Forax wrote: > Something along : > > private static MethodHandle compareAndSet(Lookup lookup, Class declaringClass, String fieldName, Class fieldType) > throws NoSuchFieldException, IllegalAccessException { > MethodHandle getter = lookup.findGetter(declaringClass, fieldName, fieldType); > MethodHandleInfo methodHandleInfo = lookup.revealDirect(getter); > Field field = methodHandleInfo.reflectAs(Field.class, lookup); > long offset = UNSAFE.objectFieldOffset(field); > MethodHandle mh = MethodHandles.insertArguments(COMPARE_AND_SWAP_OBJECT, 1, offset); > return mh.asType(MethodType.methodType(boolean.class, declaringClass, fieldType, fieldType)); > } > > public class VarHandle { > private final @Stable MethodHandle compareAndSet; > > VarHandle(MethodHandle compareAndSet) { > this.compareAndSet = compareAndSet; > } > > public boolean compareAndSet(T object, U expected, U value) { > try { > return (boolean)compareAndSet.invoke(object, expected, value); > } catch (Throwable e) { > if (e instanceof RuntimeException) throw (RuntimeException)e; > if (e instanceof Error) throw (Error)e; > throw new AssertionError(e); > } > } > } > (FWIW i initially modified the DHM code to expose out MethodHandles to CAS etc along similar lines to existing DHMs and LFs corresponding to get/putfield.) Performance-wise, as of now, the above is likely to be slower or on a par with AtomicReferenceFieldUpdater or reflection (if there was a CAS op on Field). Perhaps it will eventually be possible to achieve that with the above, but from what John says it sounds like much investigation is required. Any replacement of Unsafe in j.u.concurrent classes has to be almost, if not, as performant as that of direct Unsafe usage. It's proving quite useful to have something that works along similar fundamental lines (w.r.t. method invocation) that already gets quite close to Unsafe performance and from which we can evaluate and improve certain aspects. Paul. From forax at univ-mlv.fr Tue Sep 2 18:02:13 2014 From: forax at univ-mlv.fr (Remi Forax) Date: Tue, 02 Sep 2014 20:02:13 +0200 Subject: FTR: JVM Lang Summit presentation In-Reply-To: <7884990C-E602-4339-A557-1FDB98FBD3F7@oracle.com> References: <4ADC415B-CD55-402A-AC3E-AC8A6C0535BA@oracle.com> <53E0F9DA.3030308@univ-mlv.fr> <1FC8A755-3C36-4B5C-84AE-5A080ADBE926@oracle.com> <53E54267.4030505@univ-mlv.fr> <7884990C-E602-4339-A557-1FDB98FBD3F7@oracle.com> Message-ID: <54060625.3010301@univ-mlv.fr> On 09/02/2014 06:59 PM, Paul Sandoz wrote: > On Aug 8, 2014, at 11:34 PM, Remi Forax wrote: >> Something along : >> >> private static MethodHandle compareAndSet(Lookup lookup, Class declaringClass, String fieldName, Class fieldType) >> throws NoSuchFieldException, IllegalAccessException { >> MethodHandle getter = lookup.findGetter(declaringClass, fieldName, fieldType); >> MethodHandleInfo methodHandleInfo = lookup.revealDirect(getter); >> Field field = methodHandleInfo.reflectAs(Field.class, lookup); >> long offset = UNSAFE.objectFieldOffset(field); >> MethodHandle mh = MethodHandles.insertArguments(COMPARE_AND_SWAP_OBJECT, 1, offset); >> return mh.asType(MethodType.methodType(boolean.class, declaringClass, fieldType, fieldType)); >> } >> >> public class VarHandle { >> private final @Stable MethodHandle compareAndSet; >> >> VarHandle(MethodHandle compareAndSet) { >> this.compareAndSet = compareAndSet; >> } >> >> public boolean compareAndSet(T object, U expected, U value) { >> try { >> return (boolean)compareAndSet.invoke(object, expected, value); >> } catch (Throwable e) { >> if (e instanceof RuntimeException) throw (RuntimeException)e; >> if (e instanceof Error) throw (Error)e; >> throw new AssertionError(e); >> } >> } >> } >> > (FWIW i initially modified the DHM code to expose out MethodHandles to CAS etc along similar lines to existing DHMs and LFs corresponding to get/putfield.) > > Performance-wise, as of now, the above is likely to be slower or on a par with AtomicReferenceFieldUpdater or reflection (if there was a CAS op on Field). Perhaps it will eventually be possible to achieve that with the above, but from what John says it sounds like much investigation is required. back from vacation too, slowly trying to anwser to a pile of emails ... I was to answer yes, but I think the code can be modified a little to avoid the invoke() and use invokeExact instead so what about: private static MethodHandle compareAndSet(Lookup lookup, Class declaringClass, String fieldName, Class fieldType) throws NoSuchFieldException, IllegalAccessException { MethodHandle getter = lookup.findGetter(declaringClass, fieldName, fieldType); MethodHandleInfo methodHandleInfo = lookup.revealDirect(getter); Field field = methodHandleInfo.reflectAs(Field.class, lookup); long offset = UNSAFE.objectFieldOffset(field); MethodHandle mh = MethodHandles.insertArguments(COMPARE_AND_SWAP_OBJECT, 1, offset); return mh.asType(MethodType.methodType(boolean.class, declaringClass, fieldType, fieldType)) asType(MethodType.methodType(boolea,.class, Object.class, Object.class, Object.class)); } public class VarHandle { private final @Stable MethodHandle compareAndSet; VarHandle(MethodHandle compareAndSet) { this.compareAndSet = compareAndSet; } public boolean compareAndSet(T object, U expected, U value) { try { return (boolean)compareAndSet.invokeExact(object, expected, value); } catch (Throwable e) { if (e instanceof RuntimeException) throw (RuntimeException)e; if (e instanceof Error) throw (Error)e; throw new AssertionError(e); } } } if the VarHandle is stored in a static final, the JIT should be able to remove the downcast/upcast pair. > > Any replacement of Unsafe in j.u.concurrent classes has to be almost, if not, as performant as that of direct Unsafe usage. It's proving quite useful to have something that works along similar fundamental lines (w.r.t. method invocation) that already gets quite close to Unsafe performance and from which we can evaluate and improve certain aspects. Anyway, i still think that the best way to write a safe compareAndSet is not to use a Varandle or any polymorphic signature method, but to let the compiler generate an invokedynamic with the right signature. The bootstrap method will verify the signature once (at link time) and so the generated method handle will only do downcasts to j.l.Object, something that the JIT will trivially consider as a no-op. > > Paul. R?mi From maurizio.cimadamore at oracle.com Tue Sep 2 18:02:55 2014 From: maurizio.cimadamore at oracle.com (maurizio.cimadamore at oracle.com) Date: Tue, 02 Sep 2014 18:02:55 +0000 Subject: hg: valhalla/valhalla/langtools: Add remaining support for non-specialized generic calls. Message-ID: <201409021802.s82I2t7W027653@aojmv0008> Changeset: d8f723e8180e Author: mcimadamore Date: 2014-09-02 19:02 +0100 URL: http://hg.openjdk.java.net/valhalla/valhalla/langtools/rev/d8f723e8180e Add remaining support for non-specialized generic calls. Add support to infer unerased type information from synthetic cast during code generation. ! src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java ! src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Items.java + test/tools/javac/valhalla/typespec/items/tests/TestNonSpecializedGenericCall.java From maurizio.cimadamore at oracle.com Wed Sep 3 13:05:19 2014 From: maurizio.cimadamore at oracle.com (maurizio.cimadamore at oracle.com) Date: Wed, 03 Sep 2014 13:05:19 +0000 Subject: hg: valhalla/valhalla/langtools: Consolidate propagation of unerased types. Message-ID: <201409031305.s83D5JNm007251@aojmv0008> Changeset: dfc267d26ed8 Author: mcimadamore Date: 2014-09-03 14:04 +0100 URL: http://hg.openjdk.java.net/valhalla/valhalla/langtools/rev/dfc267d26ed8 Consolidate propagation of unerased types. Now unerased class literal info is conveyed using same field (JCExpression.unerasedType) also used in other cases. ! src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java ! src/jdk.compiler/share/classes/com/sun/tools/javac/comp/SpecializeTypes.java ! src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java ! src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java ! src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java ! test/tools/javac/failover/CheckAttributedTree.java From paul.sandoz at oracle.com Wed Sep 3 14:44:21 2014 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Wed, 3 Sep 2014 16:44:21 +0200 Subject: FTR: JVM Lang Summit presentation In-Reply-To: <54060625.3010301@univ-mlv.fr> References: <4ADC415B-CD55-402A-AC3E-AC8A6C0535BA@oracle.com> <53E0F9DA.3030308@univ-mlv.fr> <1FC8A755-3C36-4B5C-84AE-5A080ADBE926@oracle.com> <53E54267.4030505@univ-mlv.fr> <7884990C-E602-4339-A557-1FDB98FBD3F7@oracle.com> <54060625.3010301@univ-mlv.fr> Message-ID: <884DF874-327D-4409-9DD4-4EB2FCB079CC@oracle.com> On Sep 2, 2014, at 8:02 PM, Remi Forax wrote: > back from vacation too, > slowly trying to anwser to a pile of emails ... > I know how you feel :-) > I was to answer yes, but I think the code can be modified a little to avoid the invoke() and use invokeExact instead > so what about: > > private static MethodHandle compareAndSet(Lookup lookup, Class declaringClass, String fieldName, Class fieldType) > throws NoSuchFieldException, IllegalAccessException { > MethodHandle getter = lookup.findGetter(declaringClass, fieldName, fieldType); > MethodHandleInfo methodHandleInfo = lookup.revealDirect(getter); > Field field = methodHandleInfo.reflectAs(Field.class, lookup); > long offset = UNSAFE.objectFieldOffset(field); > MethodHandle mh = MethodHandles.insertArguments(COMPARE_AND_SWAP_OBJECT, 1, offset); > return mh.asType(MethodType.methodType(boolean.class, declaringClass, fieldType, fieldType)) > asType(MethodType.methodType(boolea,.class, Object.class, Object.class, Object.class)); > } > > public class VarHandle { > private final @Stable MethodHandle compareAndSet; > > VarHandle(MethodHandle compareAndSet) { > this.compareAndSet = compareAndSet; > } > > public boolean compareAndSet(T object, U expected, U value) { > try { > return (boolean)compareAndSet.invokeExact(object, expected, value); > } catch (Throwable e) { > if (e instanceof RuntimeException) throw (RuntimeException)e; > if (e instanceof Error) throw (Error)e; > throw new AssertionError(e); > } > } > } > > if the VarHandle is stored in a static final, the JIT should be able to remove the downcast/upcast pair. > Thanks, that's a rather neat trick! It triggered the following thought, why not just do (assuming identical access control checks on construction of the handle): public boolean compareAndSet_direct(R r, V e, V v) { r.getClass(); // check for null MethodHandleImpl.castReference(rType, r); MethodHandleImpl.castReference(vType, e); MethodHandleImpl.castReference(vType, v); return MethodHandleStatics.UNSAFE.compareAndSwapObject(r, v_offset, e, v); } There is no class spinning and the inline trace is much smaller (although much could be reduced with specific D-like MHs). I experimented a bit with both of the above (see end of email for code) and each gets really rather close perf-wise and assembly-wise. I never quite realized how aggressive the JIT is at optimizing this area. Those casts can get reduced to almost no-ops (like the possibly redundant cast of the value in accessor DHMs). There are some redundant null-checks, as previously discussed on core-libs. Are those casts always guaranteed to get optimized away if the handle is static final and an invocation on that handle is inlined? >> >> Any replacement of Unsafe in j.u.concurrent classes has to be almost, if not, as performant as that of direct Unsafe usage. It's proving quite useful to have something that works along similar fundamental lines (w.r.t. method invocation) that already gets quite close to Unsafe performance and from which we can evaluate and improve certain aspects. > > Anyway, i still think that the best way to write a safe compareAndSet is not to use a Varandle or any polymorphic signature method, but to let the compiler generate an invokedynamic with the right signature. The bootstrap method will verify the signature once (at link time) and so the generated method handle will only do downcasts to j.l.Object, something that the JIT will trivially consider as a no-op. > I consider that as possible further steps, requiring some syntax bike shedding and a mechanism for how javac produces the indy call. Regardless we still need to evaluate the low-level plumbing. Paul. From paul.sandoz at oracle.com Wed Sep 3 14:49:43 2014 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Wed, 3 Sep 2014 16:49:43 +0200 Subject: FTR: JVM Lang Summit presentation In-Reply-To: <884DF874-327D-4409-9DD4-4EB2FCB079CC@oracle.com> References: <4ADC415B-CD55-402A-AC3E-AC8A6C0535BA@oracle.com> <53E0F9DA.3030308@univ-mlv.fr> <1FC8A755-3C36-4B5C-84AE-5A080ADBE926@oracle.com> <53E54267.4030505@univ-mlv.fr> <7884990C-E602-4339-A557-1FDB98FBD3F7@oracle.com> <54060625.3010301@univ-mlv.fr> <884DF874-327D-4409-9DD4-4EB2FCB079CC@oracle.com> Message-ID: On Sep 3, 2014, at 4:44 PM, Paul Sandoz wrote: > I experimented a bit with both of the above (see end of email for code) Drat, i forgot to add the code in the last email, Paul. package java.lang.invoke; import sun.misc.Unsafe; import java.lang.reflect.Field; public final class RefFieldVarHandle { private final MethodHandle getVolatile; private final MethodHandle setVolatile; private final MethodHandle setRelease; private final MethodHandle compareAndSet; private final Class rType; private final Class vType; private final long v_offset; RefFieldVarHandle(MethodHandle getVolatile, MethodHandle setVolatile, MethodHandle setRelease, MethodHandle compareAndSet, Class rType, Class vType, long v_offset) { this.getVolatile = getVolatile; this.setVolatile = setVolatile; this.setRelease = setRelease; this.compareAndSet = compareAndSet; this.rType = rType; this.vType = vType; this.v_offset = v_offset; } @ForceInline public boolean compareAndSet_mh(R r, V e, V v) { r.getClass(); // check for null try { return (boolean) compareAndSet.invokeExact(r, e, v); } catch (Throwable t) { if (t instanceof RuntimeException) throw (RuntimeException) t; if (t instanceof Error) throw (Error) t; throw new AssertionError(t); } } @ForceInline public boolean compareAndSet_direct(R r, V e, V v) { r.getClass(); // check for null MethodHandleImpl.castReference(rType, r); MethodHandleImpl.castReference(vType, e); MethodHandleImpl.castReference(vType, v); return MethodHandleStatics.UNSAFE.compareAndSwapObject(r, v_offset, e, v); } @ForceInline @SuppressWarnings("unchecked") public V getVolatile_mh(R r) { r.getClass(); // check for null try { Object v = (Object) getVolatile.invokeExact(r); return (V) v; } catch (Throwable t) { if (t instanceof RuntimeException) throw (RuntimeException) t; if (t instanceof Error) throw (Error) t; throw new AssertionError(t); } } @ForceInline public V getVolatile_direct(R r) { r.getClass(); // check for null Object v = MethodHandleStatics.UNSAFE.getObjectVolatile(r, v_offset); return MethodHandleImpl.castReference(vType, v); } @ForceInline public void setVolatile_mh(R r, V v) { r.getClass(); // check for null try { setVolatile.invokeExact(r, v); } catch (Throwable t) { if (t instanceof RuntimeException) throw (RuntimeException) t; if (t instanceof Error) throw (Error) t; throw new AssertionError(t); } } @ForceInline public void setVolatile_direct(R r, V v) { r.getClass(); // check for null MethodHandleImpl.castReference(rType, r); MethodHandleImpl.castReference(vType, v); MethodHandleStatics.UNSAFE.putObjectVolatile(r, v_offset, v); } @ForceInline public void setRelease_mh(R r, V v) { r.getClass(); // check for null try { setRelease.invokeExact(r, v); } catch (Throwable t) { if (t instanceof RuntimeException) throw (RuntimeException) t; if (t instanceof Error) throw (Error) t; throw new AssertionError(t); } } @ForceInline public void setRelease_direct(R r, V v) { r.getClass(); // check for null MethodHandleImpl.castReference(rType, r); MethodHandleImpl.castReference(vType, v); MethodHandleStatics.UNSAFE.putOrderedObject(r, v_offset, v); } public static RefFieldVarHandle findHandle(Class r, String name, Class v) throws NoSuchFieldException, IllegalAccessException { MethodHandles.Lookup lookup = MethodHandles.Lookup.IMPL_LOOKUP; MethodHandle getter = lookup.findGetter(r, name, v); MethodHandleInfo methodHandleInfo = lookup.revealDirect(getter); Field field = methodHandleInfo.reflectAs(Field.class, lookup); long offset = MethodHandleStatics.UNSAFE.objectFieldOffset(field); MethodHandle getVolatile = MethodHandles.insertArguments(GET_VOLATILE_OBJECT, 1, offset); getVolatile = getVolatile.asType(MethodType.methodType(v, r)); getVolatile = getVolatile.asType(MethodType.methodType(Object.class, Object.class)); MethodHandle setVolatile = MethodHandles.insertArguments(SET_VOLATILE_OBJECT, 1, offset); setVolatile = setVolatile.asType(MethodType.methodType(void.class, r, v)); setVolatile = setVolatile.asType(MethodType.methodType(void.class, Object.class, Object.class)); MethodHandle setRelease = MethodHandles.insertArguments(SET_RELEASE_OBJECT, 1, offset); setRelease = setRelease.asType(MethodType.methodType(void.class, r, v)); setRelease = setRelease.asType(MethodType.methodType(void.class, Object.class, Object.class)); MethodHandle cas = MethodHandles.insertArguments(COMPARE_AND_SWAP_OBJECT, 1, offset); cas = cas.asType(MethodType.methodType(boolean.class, r, v, v)); cas = cas.asType(MethodType.methodType(boolean.class, Object.class, Object.class, Object.class)); return new RefFieldVarHandle<>( getVolatile, setVolatile, setRelease, cas, r, v, offset); } static final MethodHandle GET_VOLATILE_OBJECT; static final MethodHandle SET_VOLATILE_OBJECT; static final MethodHandle SET_RELEASE_OBJECT; static final MethodHandle COMPARE_AND_SWAP_OBJECT; static { try { MethodHandle getVolatile = MethodHandles.Lookup.IMPL_LOOKUP.findVirtual( Unsafe.class, "getObjectVolatile", MethodType.methodType(Object.class, Object.class, long.class)); GET_VOLATILE_OBJECT = MethodHandles.insertArguments(getVolatile, 0, MethodHandleStatics.UNSAFE); MethodHandle setVolatile = MethodHandles.Lookup.IMPL_LOOKUP.findVirtual( Unsafe.class, "putObjectVolatile", MethodType.methodType(void.class, Object.class, long.class, Object.class)); SET_VOLATILE_OBJECT = MethodHandles.insertArguments(setVolatile, 0, MethodHandleStatics.UNSAFE); MethodHandle setRelease = MethodHandles.Lookup.IMPL_LOOKUP.findVirtual( Unsafe.class, "putOrderedObject", MethodType.methodType(void.class, Object.class, long.class, Object.class)); SET_RELEASE_OBJECT = MethodHandles.insertArguments(setRelease, 0, MethodHandleStatics.UNSAFE); MethodHandle cas = MethodHandles.Lookup.IMPL_LOOKUP.findVirtual( Unsafe.class, "compareAndSwapObject", MethodType.methodType(boolean.class, Object.class, long.class, Object.class, Object.class)); COMPARE_AND_SWAP_OBJECT = MethodHandles.insertArguments(cas, 0, MethodHandleStatics.UNSAFE); } catch (Exception e) { throw new AssertionError(e); } } } From forax at univ-mlv.fr Wed Sep 3 15:28:40 2014 From: forax at univ-mlv.fr (Remi Forax) Date: Wed, 03 Sep 2014 17:28:40 +0200 Subject: FTR: JVM Lang Summit presentation In-Reply-To: <884DF874-327D-4409-9DD4-4EB2FCB079CC@oracle.com> References: <4ADC415B-CD55-402A-AC3E-AC8A6C0535BA@oracle.com> <53E0F9DA.3030308@univ-mlv.fr> <1FC8A755-3C36-4B5C-84AE-5A080ADBE926@oracle.com> <53E54267.4030505@univ-mlv.fr> <7884990C-E602-4339-A557-1FDB98FBD3F7@oracle.com> <54060625.3010301@univ-mlv.fr> <884DF874-327D-4409-9DD4-4EB2FCB079CC@oracle.com> Message-ID: <540733A8.4060208@univ-mlv.fr> On 09/03/2014 04:44 PM, Paul Sandoz wrote: > On Sep 2, 2014, at 8:02 PM, Remi Forax wrote: >> back from vacation too, >> slowly trying to anwser to a pile of emails ... >> > I know how you feel :-) A drawback of the 5 weeks of vacation policy in France :) > > >> I was to answer yes, but I think the code can be modified a little to avoid the invoke() and use invokeExact instead >> so what about: >> >> private static MethodHandle compareAndSet(Lookup lookup, Class declaringClass, String fieldName, Class fieldType) >> throws NoSuchFieldException, IllegalAccessException { >> MethodHandle getter = lookup.findGetter(declaringClass, fieldName, fieldType); >> MethodHandleInfo methodHandleInfo = lookup.revealDirect(getter); >> Field field = methodHandleInfo.reflectAs(Field.class, lookup); >> long offset = UNSAFE.objectFieldOffset(field); >> MethodHandle mh = MethodHandles.insertArguments(COMPARE_AND_SWAP_OBJECT, 1, offset); >> return mh.asType(MethodType.methodType(boolean.class, declaringClass, fieldType, fieldType)) >> asType(MethodType.methodType(boolea,.class, Object.class, Object.class, Object.class)); >> } >> >> public class VarHandle { >> private final @Stable MethodHandle compareAndSet; >> >> VarHandle(MethodHandle compareAndSet) { >> this.compareAndSet = compareAndSet; >> } >> >> public boolean compareAndSet(T object, U expected, U value) { >> try { >> return (boolean)compareAndSet.invokeExact(object, expected, value); >> } catch (Throwable e) { >> if (e instanceof RuntimeException) throw (RuntimeException)e; >> if (e instanceof Error) throw (Error)e; >> throw new AssertionError(e); >> } >> } >> } >> >> if the VarHandle is stored in a static final, the JIT should be able to remove the downcast/upcast pair. >> > Thanks, that's a rather neat trick! > > It triggered the following thought, why not just do (assuming identical access control checks on construction of the handle): > > public boolean compareAndSet_direct(R r, V e, V v) { > r.getClass(); // check for null > MethodHandleImpl.castReference(rType, r); > MethodHandleImpl.castReference(vType, e); > MethodHandleImpl.castReference(vType, v); > return MethodHandleStatics.UNSAFE.compareAndSwapObject(r, v_offset, e, v); > } > > There is no class spinning and the inline trace is much smaller (although much could be reduced with specific D-like MHs). > > I experimented a bit with both of the above (see end of email for code) and each gets really rather close perf-wise and assembly-wise. I never quite realized how aggressive the JIT is at optimizing this area. Those casts can get reduced to almost no-ops (like the possibly redundant cast of the value in accessor DHMs). There are some redundant null-checks, as previously discussed on core-libs. I use mh instead of plain code to avoid profile pollution. The profile is attached to the mh tree so you have as many profile sites as VarHandles instead of having one (or three in fact) profile site for all VarHandles. Maybe it's not needed, I don't know. > > Are those casts always guaranteed to get optimized away if the handle is static final and an invocation on that handle is inlined? good question, indeed. > > >>> Any replacement of Unsafe in j.u.concurrent classes has to be almost, if not, as performant as that of direct Unsafe usage. It's proving quite useful to have something that works along similar fundamental lines (w.r.t. method invocation) that already gets quite close to Unsafe performance and from which we can evaluate and improve certain aspects. >> Anyway, i still think that the best way to write a safe compareAndSet is not to use a Varandle or any polymorphic signature method, but to let the compiler generate an invokedynamic with the right signature. The bootstrap method will verify the signature once (at link time) and so the generated method handle will only do downcasts to j.l.Object, something that the JIT will trivially consider as a no-op. >> > I consider that as possible further steps, requiring some syntax bike shedding and a mechanism for how javac produces the indy call. Regardless we still need to evaluate the low-level plumbing. but what you call a 'further step' removes the need to those castReference calls, making the low-level plumbing easier. > > Paul. > > R?mi From paul.sandoz at oracle.com Wed Sep 3 16:26:15 2014 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Wed, 3 Sep 2014 18:26:15 +0200 Subject: FTR: JVM Lang Summit presentation In-Reply-To: <540733A8.4060208@univ-mlv.fr> References: <4ADC415B-CD55-402A-AC3E-AC8A6C0535BA@oracle.com> <53E0F9DA.3030308@univ-mlv.fr> <1FC8A755-3C36-4B5C-84AE-5A080ADBE926@oracle.com> <53E54267.4030505@univ-mlv.fr> <7884990C-E602-4339-A557-1FDB98FBD3F7@oracle.com> <54060625.3010301@univ-mlv.fr> <884DF874-327D-4409-9DD4-4EB2FCB079CC@oracle.com> <540733A8.4060208@univ-mlv.fr> Message-ID: <081A4167-766C-4AAE-ABE8-309F1833E0B8@oracle.com> On Sep 3, 2014, at 5:28 PM, Remi Forax wrote: > > On 09/03/2014 04:44 PM, Paul Sandoz wrote: >> On Sep 2, 2014, at 8:02 PM, Remi Forax wrote: >>> back from vacation too, >>> slowly trying to anwser to a pile of emails ... >>> >> I know how you feel :-) > > A drawback of the 5 weeks of vacation policy in France :) > C'est dur... >> >> I experimented a bit with both of the above (see end of email for code) and each gets really rather close perf-wise and assembly-wise. I never quite realized how aggressive the JIT is at optimizing this area. Those casts can get reduced to almost no-ops (like the possibly redundant cast of the value in accessor DHMs). There are some redundant null-checks, as previously discussed on core-libs. > > I use mh instead of plain code to avoid profile pollution. I tried and failed to cause profile pollution in both cases with some simple examples. Same applies to VarHandles in the repo too. > The profile is attached to the mh tree so you have as many profile sites as VarHandles instead of having one (or three in fact) profile site for all VarHandles. W.r.t. VarHandles in the repo: IIUC invokehandle is a profile point (by default for 2 ref args) so the invokeExact side of VarHandles is covered. However, since VarHandles are not currently using LFs there is no type profiling of the args/params of the static methods. > Maybe it's not needed, I don't know. Since there are no specific operations performed on the instances of R and V is there anything gained by type profiling? How would the shape of the inlining differ for different ref receiver/value types? > >> >> Are those casts always guaranteed to get optimized away if the handle is static final and an invocation on that handle is inlined? > > good question, indeed. > Oh, i was hoping you would know :-) >> >> >>>> Any replacement of Unsafe in j.u.concurrent classes has to be almost, if not, as performant as that of direct Unsafe usage. It's proving quite useful to have something that works along similar fundamental lines (w.r.t. method invocation) that already gets quite close to Unsafe performance and from which we can evaluate and improve certain aspects. >>> Anyway, i still think that the best way to write a safe compareAndSet is not to use a Varandle or any polymorphic signature method, but to let the compiler generate an invokedynamic with the right signature. The bootstrap method will verify the signature once (at link time) and so the generated method handle will only do downcasts to j.l.Object, something that the JIT will trivially consider as a no-op. >>> >> I consider that as possible further steps, requiring some syntax bike shedding and a mechanism for how javac produces the indy call. Regardless we still need to evaluate the low-level plumbing. > > but what you call a 'further step' removes the need to those castReference calls, making the low-level plumbing easier. > I am already at the low-level pluming stage, in this respect there is no need at the moment to start syntax bashing and generating indy calls. For example, a Class.cast on a value (not a receiver) is performed by both DHMs and VarHandles (which has an option to switch 'em off). Originally i thought they were for type profiling but i am not so sure now. I need to perform an experiment turning those casts in accessor LFs of DMHs to asserts and running it through a bunch of stress tests. Same goes for VHs e.g. running JSR 166 loops tests. If the cast is needed for DHMs we can work to optimise it so it does not leave redundant null-checks around. Otherwise we can remove it, and perhaps not bother optimising it unless it would be handy for other cases as well (like for those in the RefFieldVarHandle class). Paul. From maurizio.cimadamore at oracle.com Wed Sep 3 16:43:59 2014 From: maurizio.cimadamore at oracle.com (maurizio.cimadamore at oracle.com) Date: Wed, 03 Sep 2014 16:43:59 +0000 Subject: hg: valhalla/valhalla/langtools: Add support for specialized generic constructors calls. Message-ID: <201409031644.s83Gi0W8014441@aojmv0008> Changeset: ce8839ea4054 Author: mcimadamore Date: 2014-09-03 17:43 +0100 URL: http://hg.openjdk.java.net/valhalla/valhalla/langtools/rev/ce8839ea4054 Add support for specialized generic constructors calls. ! src/jdk.compiler/share/classes/com/sun/tools/javac/comp/IndifierTranslator.java ! src/jdk.compiler/share/classes/com/sun/tools/javac/comp/SpecializeTypes.java ! src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Items.java + test/tools/javac/valhalla/typespec/items/tests/TestGenericSpecializedConstructor.java From paul.sandoz at oracle.com Wed Sep 3 19:31:55 2014 From: paul.sandoz at oracle.com (paul.sandoz at oracle.com) Date: Wed, 03 Sep 2014 19:31:55 +0000 Subject: hg: valhalla/valhalla/jdk: Use Unsafe.getAndSetX which is an intrinsic. Message-ID: <201409031931.s83JVtf0011818@aojmv0008> Changeset: 5259c21704b9 Author: psandoz Date: 2014-09-03 21:19 +0200 URL: http://hg.openjdk.java.net/valhalla/valhalla/jdk/rev/5259c21704b9 Use Unsafe.getAndSetX which is an intrinsic. ! src/java.base/share/classes/java/lang/invoke/ArrayIntArrayHandle.java ! src/java.base/share/classes/java/lang/invoke/ArrayRefArrayHandle.java ! src/java.base/share/classes/java/lang/invoke/ArrayRefHandle.java ! src/java.base/share/classes/java/lang/invoke/ArrayRefNoCastHandle.java ! src/java.base/share/classes/java/lang/invoke/FieldInstanceIntFieldHandle.java ! src/java.base/share/classes/java/lang/invoke/FieldInstanceIntHandle.java ! src/java.base/share/classes/java/lang/invoke/FieldInstanceLongHandle.java ! src/java.base/share/classes/java/lang/invoke/FieldInstanceRefFieldHandle.java ! src/java.base/share/classes/java/lang/invoke/FieldInstanceRefHandle.java ! src/java.base/share/classes/java/lang/invoke/FieldInstanceRefNoCastHandle.java ! src/java.base/share/classes/java/lang/invoke/OffHeapRegion.java From forax at univ-mlv.fr Thu Sep 4 09:29:07 2014 From: forax at univ-mlv.fr (Remi Forax) Date: Thu, 04 Sep 2014 11:29:07 +0200 Subject: FTR: JVM Lang Summit presentation In-Reply-To: <081A4167-766C-4AAE-ABE8-309F1833E0B8@oracle.com> References: <4ADC415B-CD55-402A-AC3E-AC8A6C0535BA@oracle.com> <53E0F9DA.3030308@univ-mlv.fr> <1FC8A755-3C36-4B5C-84AE-5A080ADBE926@oracle.com> <53E54267.4030505@univ-mlv.fr> <7884990C-E602-4339-A557-1FDB98FBD3F7@oracle.com> <54060625.3010301@univ-mlv.fr> <884DF874-327D-4409-9DD4-4EB2FCB079CC@oracle.com> <540733A8.4060208@univ-mlv.fr> <081A4167-766C-4AAE-ABE8-309F1833E0B8@oracle.com> Message-ID: <540830E3.4060300@univ-mlv.fr> On 09/03/2014 06:26 PM, Paul Sandoz wrote: > On Sep 3, 2014, at 5:28 PM, Remi Forax wrote: > >> On 09/03/2014 04:44 PM, Paul Sandoz wrote: >>> On Sep 2, 2014, at 8:02 PM, Remi Forax wrote: >>>> back from vacation too, >>>> slowly trying to anwser to a pile of emails ... >>>> >>> I know how you feel :-) >> A drawback of the 5 weeks of vacation policy in France :) >> > C'est dur... > > >>> I experimented a bit with both of the above (see end of email for code) and each gets really rather close perf-wise and assembly-wise. I never quite realized how aggressive the JIT is at optimizing this area. Those casts can get reduced to almost no-ops (like the possibly redundant cast of the value in accessor DHMs). There are some redundant null-checks, as previously discussed on core-libs. >> I use mh instead of plain code to avoid profile pollution. > I tried and failed to cause profile pollution in both cases with some simple examples. Same applies to VarHandles in the repo too. Do you have tested to call the same VarHandle.compareAndSet with different classes like by example if you have a linked list with two classes as possible implementation of a link ? > > >> The profile is attached to the mh tree so you have as many profile sites as VarHandles instead of having one (or three in fact) profile site for all VarHandles. > W.r.t. VarHandles in the repo: IIUC invokehandle is a profile point (by default for 2 ref args) so the invokeExact side of VarHandles is covered. However, since VarHandles are not currently using LFs there is no type profiling of the args/params of the static methods. > > >> Maybe it's not needed, I don't know. > Since there are no specific operations performed on the instances of R and V is there anything gained by type profiling? How would the shape of the inlining differ for different ref receiver/value types? You still ask to do classchecks on instances of R and V, if the JIT is always able to do type propagation from the call site, then it can remove them, if type propagation fail, it will relies on type profiling, if there is only one profile, the classcheck will be compiled to a cheap pointer check, if there is type pollution, the generated code may start to be expensive (relatively). > > >>> Are those casts always guaranteed to get optimized away if the handle is static final and an invocation on that handle is inlined? >> good question, indeed. >> > Oh, i was hoping you would know :-) I don't know what @ForceInline does exactly, i.e. is it enough to guarantee type propagation or not ? > > >>> >>>>> Any replacement of Unsafe in j.u.concurrent classes has to be almost, if not, as performant as that of direct Unsafe usage. It's proving quite useful to have something that works along similar fundamental lines (w.r.t. method invocation) that already gets quite close to Unsafe performance and from which we can evaluate and improve certain aspects. >>>> Anyway, i still think that the best way to write a safe compareAndSet is not to use a Varandle or any polymorphic signature method, but to let the compiler generate an invokedynamic with the right signature. The bootstrap method will verify the signature once (at link time) and so the generated method handle will only do downcasts to j.l.Object, something that the JIT will trivially consider as a no-op. >>>> >>> I consider that as possible further steps, requiring some syntax bike shedding and a mechanism for how javac produces the indy call. Regardless we still need to evaluate the low-level plumbing. >> but what you call a 'further step' removes the need to those castReference calls, making the low-level plumbing easier. >> > I am already at the low-level pluming stage, in this respect there is no need at the moment to start syntax bashing and generating indy calls. I'm not talking about syntax but semantics. As I wrote earlier, I don't think it's a good idea to have a DSL inside Java especially when you can solve the problem using an API. Talking about semantics, the question is: does the type of the arguments are erased to Object or not ? If the types of the argument are erased, you have to explain to the JIT that you want to remove the checkcasts, if the types of the argument are not erased, the is no problem. > > For example, a Class.cast on a value (not a receiver) is performed by both DHMs and VarHandles (which has an option to switch 'em off). Originally i thought they were for type profiling but i am not so sure now. > > I need to perform an experiment turning those casts in accessor LFs of DMHs to asserts and running it through a bunch of stress tests. Same goes for VHs e.g. running JSR 166 loops tests. > > If the cast is needed for DHMs we can work to optimise it so it does not leave redundant null-checks around. Otherwise we can remove it, and perhaps not bother optimising it unless it would be handy for other cases as well (like for those in the RefFieldVarHandle class). > > Paul. R?mi From paul.sandoz at oracle.com Thu Sep 4 11:26:38 2014 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Thu, 4 Sep 2014 13:26:38 +0200 Subject: FTR: JVM Lang Summit presentation In-Reply-To: <540830E3.4060300@univ-mlv.fr> References: <4ADC415B-CD55-402A-AC3E-AC8A6C0535BA@oracle.com> <53E0F9DA.3030308@univ-mlv.fr> <1FC8A755-3C36-4B5C-84AE-5A080ADBE926@oracle.com> <53E54267.4030505@univ-mlv.fr> <7884990C-E602-4339-A557-1FDB98FBD3F7@oracle.com> <54060625.3010301@univ-mlv.fr> <884DF874-327D-4409-9DD4-4EB2FCB079CC@oracle.com> <540733A8.4060208@univ-mlv.fr> <081A4167-766C-4AAE-ABE8-309F1833E0B8@oracle.com> <540830E3.4060300@univ-mlv.fr> Message-ID: <6B29D8AC-4AF7-413F-8BE1-28F56262DE9D@oracle.com> On Sep 4, 2014, at 11:29 AM, Remi Forax wrote: >>>> I experimented a bit with both of the above (see end of email for code) and each gets really rather close perf-wise and assembly-wise. I never quite realized how aggressive the JIT is at optimizing this area. Those casts can get reduced to almost no-ops (like the possibly redundant cast of the value in accessor DHMs). There are some redundant null-checks, as previously discussed on core-libs. >>> I use mh instead of plain code to avoid profile pollution. >> I tried and failed to cause profile pollution in both cases with some simple examples. Same applies to VarHandles in the repo too. > > > > Do you have tested to call the same VarHandle.compareAndSet with different classes like by example if you have a linked list with two classes as possible implementation of a link ? > Not quite sure what you mean with the list example, but i have tested a static final instance of that RefFieldVarHandle class with calls to compareAndSet and multiple sub-classes of the receiver and value types. >> >> >>> The profile is attached to the mh tree so you have as many profile sites as VarHandles instead of having one (or three in fact) profile site for all VarHandles. >> W.r.t. VarHandles in the repo: IIUC invokehandle is a profile point (by default for 2 ref args) so the invokeExact side of VarHandles is covered. However, since VarHandles are not currently using LFs there is no type profiling of the args/params of the static methods. >> >> >>> Maybe it's not needed, I don't know. >> Since there are no specific operations performed on the instances of R and V is there anything gained by type profiling? How would the shape of the inlining differ for different ref receiver/value types? > > You still ask to do classchecks on instances of R and V, > if the JIT is always able to do type propagation from the call site, then it can remove them, Yes, that is the case i was referring to. > if type propagation fail, it will relies on type profiling, if there is only one profile, the classcheck will be compiled to a cheap pointer check, > if there is type pollution, the generated code may start to be expensive (relatively). > Thanks, i observe that case for compiled methods on RefFieldVarHandle. Interestingly it seems for static final instances of AtomicReferenceFieldUpdater the type propagation may be failing. Perhaps this is due to certain other checks getting in the way, such as explicit class pointer checks. (Also i dunno if it is also because the class's methods are abstract.) As an experiment it may be worth simplifying the AtomicReferenceFieldUpdater implementation and remove pre-cursor checks that try and avoid instanceOf checks (plus perhaps the underlying impl could be split in two for support of the less common case of protected access). >> >> >>>> Are those casts always guaranteed to get optimized away if the handle is static final and an invocation on that handle is inlined? >>> good question, indeed. >>> >> Oh, i was hoping you would know :-) > > I don't know what @ForceInline does exactly, IIUC it tells the compiler to ignore certain details when inlining the annotated method, such as code size and inline level limits (and i also presume whether the method is hot), perhaps just like as if one told the compiler to explicitly inline a method via XX options. > i.e. is it enough to guarantee type propagation or not ? > Might be. I dunno for the case of more general MH chains. As John said in a previous email on core-libs there are...: "... some awkward looking "belt and suspenders" MH internals, such as the free use of casts in LF bytecode rendering." >> >> >>>> >>>>>> Any replacement of Unsafe in j.u.concurrent classes has to be almost, if not, as performant as that of direct Unsafe usage. It's proving quite useful to have something that works along similar fundamental lines (w.r.t. method invocation) that already gets quite close to Unsafe performance and from which we can evaluate and improve certain aspects. >>>>> Anyway, i still think that the best way to write a safe compareAndSet is not to use a Varandle or any polymorphic signature method, but to let the compiler generate an invokedynamic with the right signature. The bootstrap method will verify the signature once (at link time) and so the generated method handle will only do downcasts to j.l.Object, something that the JIT will trivially consider as a no-op. >>>>> >>>> I consider that as possible further steps, requiring some syntax bike shedding and a mechanism for how javac produces the indy call. Regardless we still need to evaluate the low-level plumbing. >>> but what you call a 'further step' removes the need to those castReference calls, making the low-level plumbing easier. >>> >> I am already at the low-level pluming stage, in this respect there is no need at the moment to start syntax bashing and generating indy calls. > > I'm not talking about syntax but semantics. We may be talking across each other a little bit too :-) > As I wrote earlier, I don't think it's a good idea to have a DSL inside Java especially when you can solve the problem using an API. > Talking about semantics, the question is: does the type of the arguments are erased to Object or not ? > If the types of the argument are erased, you have to explain to the JIT that you want to remove the checkcasts, > if the types of the argument are not erased, the is no problem. > For the case of a poly sig method invocation the types are encoded at the call site, so for static final DHMs/VHs if the invocation is successful and gets inlined (which it should be forced to do when the calling method gets inlined) then it might be OK to remove the explicit cast on the value [*] Paul. [*] http://hg.openjdk.java.net/valhalla/valhalla/jdk/file/5259c21704b9/src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java#l436 http://hg.openjdk.java.net/valhalla/valhalla/jdk/file/5259c21704b9/src/java.base/share/classes/java/lang/invoke/FieldInstanceRefHandle.java#l74 From forax at univ-mlv.fr Thu Sep 4 12:29:41 2014 From: forax at univ-mlv.fr (Remi Forax) Date: Thu, 04 Sep 2014 14:29:41 +0200 Subject: FTR: JVM Lang Summit presentation In-Reply-To: <6B29D8AC-4AF7-413F-8BE1-28F56262DE9D@oracle.com> References: <4ADC415B-CD55-402A-AC3E-AC8A6C0535BA@oracle.com> <53E0F9DA.3030308@univ-mlv.fr> <1FC8A755-3C36-4B5C-84AE-5A080ADBE926@oracle.com> <53E54267.4030505@univ-mlv.fr> <7884990C-E602-4339-A557-1FDB98FBD3F7@oracle.com> <54060625.3010301@univ-mlv.fr> <884DF874-327D-4409-9DD4-4EB2FCB079CC@oracle.com> <540733A8.4060208@univ-mlv.fr> <081A4167-766C-4AAE-ABE8-309F1833E0B8@oracle.com> <540830E3.4060300@univ-mlv.fr> <6B29D8AC-4AF7-413F-8BE1-28F56262DE9D@oracle.com> Message-ID: <54085B35.4030606@univ-mlv.fr> On 09/04/2014 01:26 PM, Paul Sandoz wrote: > On Sep 4, 2014, at 11:29 AM, Remi Forax wrote: >>>>> I experimented a bit with both of the above (see end of email for code) and each gets really rather close perf-wise and assembly-wise. I never quite realized how aggressive the JIT is at optimizing this area. Those casts can get reduced to almost no-ops (like the possibly redundant cast of the value in accessor DHMs). There are some redundant null-checks, as previously discussed on core-libs. >>>> I use mh instead of plain code to avoid profile pollution. >>> I tried and failed to cause profile pollution in both cases with some simple examples. Same applies to VarHandles in the repo too. >> >> >> Do you have tested to call the same VarHandle.compareAndSet with different classes like by example if you have a linked list with two classes as possible implementation of a link ? >> > Not quite sure what you mean with the list example, but i have tested a static final instance of that RefFieldVarHandle class with calls to compareAndSet and multiple sub-classes of the receiver and value types. The same call site called with different arguments or several calls with different arguments. The former may lead to profile pollution, not the later. > > >>> >>>> The profile is attached to the mh tree so you have as many profile sites as VarHandles instead of having one (or three in fact) profile site for all VarHandles. >>> W.r.t. VarHandles in the repo: IIUC invokehandle is a profile point (by default for 2 ref args) so the invokeExact side of VarHandles is covered. However, since VarHandles are not currently using LFs there is no type profiling of the args/params of the static methods. >>> >>> >>>> Maybe it's not needed, I don't know. >>> Since there are no specific operations performed on the instances of R and V is there anything gained by type profiling? How would the shape of the inlining differ for different ref receiver/value types? >> You still ask to do classchecks on instances of R and V, >> if the JIT is always able to do type propagation from the call site, then it can remove them, > Yes, that is the case i was referring to. > > >> if type propagation fail, it will relies on type profiling, if there is only one profile, the classcheck will be compiled to a cheap pointer check, >> if there is type pollution, the generated code may start to be expensive (relatively). >> > Thanks, i observe that case for compiled methods on RefFieldVarHandle. > > Interestingly it seems for static final instances of AtomicReferenceFieldUpdater the type propagation may be failing. Perhaps this is due to certain other checks getting in the way, such as explicit class pointer checks. (Also i dunno if it is also because the class's methods are abstract.) I think, it's due to the fact that RefFieldVarHandle is declared in package java.lang.invoke which is special, the VM considers that the fields of classes of this package can not be changed by reflection thus the JIT can optimize through them. > > As an experiment it may be worth simplifying the AtomicReferenceFieldUpdater implementation and remove pre-cursor checks that try and avoid instanceOf checks (plus perhaps the underlying impl could be split in two for support of the less common case of protected access). moving AtomicReferenceFieldUpdater to java.lang.invoke should be enough. > > >>> >>>>> Are those casts always guaranteed to get optimized away if the handle is static final and an invocation on that handle is inlined? >>>> good question, indeed. >>>> >>> Oh, i was hoping you would know :-) >> I don't know what @ForceInline does exactly, > IIUC it tells the compiler to ignore certain details when inlining the annotated method, such as code size and inline level limits (and i also presume whether the method is hot), perhaps just like as if one told the compiler to explicitly inline a method via XX options. > > >> i.e. is it enough to guarantee type propagation or not ? >> > Might be. > > I dunno for the case of more general MH chains. As John said in a previous email on core-libs there are...: > > "... some awkward looking "belt and suspenders" MH internals, such as the free use of casts in LF bytecode rendering." > > >>> >>>>>>> Any replacement of Unsafe in j.u.concurrent classes has to be almost, if not, as performant as that of direct Unsafe usage. It's proving quite useful to have something that works along similar fundamental lines (w.r.t. method invocation) that already gets quite close to Unsafe performance and from which we can evaluate and improve certain aspects. >>>>>> Anyway, i still think that the best way to write a safe compareAndSet is not to use a Varandle or any polymorphic signature method, but to let the compiler generate an invokedynamic with the right signature. The bootstrap method will verify the signature once (at link time) and so the generated method handle will only do downcasts to j.l.Object, something that the JIT will trivially consider as a no-op. >>>>>> >>>>> I consider that as possible further steps, requiring some syntax bike shedding and a mechanism for how javac produces the indy call. Regardless we still need to evaluate the low-level plumbing. >>>> but what you call a 'further step' removes the need to those castReference calls, making the low-level plumbing easier. >>>> >>> I am already at the low-level pluming stage, in this respect there is no need at the moment to start syntax bashing and generating indy calls. >> I'm not talking about syntax but semantics. > We may be talking across each other a little bit too :-) > > >> As I wrote earlier, I don't think it's a good idea to have a DSL inside Java especially when you can solve the problem using an API. >> Talking about semantics, the question is: does the type of the arguments are erased to Object or not ? >> If the types of the argument are erased, you have to explain to the JIT that you want to remove the checkcasts, >> if the types of the argument are not erased, the is no problem. >> > For the case of a poly sig method invocation the types are encoded at the call site, so for static final DHMs/VHs if the invocation is successful and gets inlined (which it should be forced to do when the calling method gets inlined) then it might be OK to remove the explicit cast on the value [*] poly sig is a lot of things, it's the sum of - a special type calculation rule in javac - a variable arity signature - a special (two in fact) semantics of calling for the VM in our case, we only need the first item plus invokedynamic to avoid to have to specify another specific semantics in the JLS, that's why I think that poly sig is not the best vehicle for implementing type safe compareAndSet and friends. > > Paul. > > [*] > http://hg.openjdk.java.net/valhalla/valhalla/jdk/file/5259c21704b9/src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java#l436 > http://hg.openjdk.java.net/valhalla/valhalla/jdk/file/5259c21704b9/src/java.base/share/classes/java/lang/invoke/FieldInstanceRefHandle.java#l74 > > R?mi From paul.sandoz at oracle.com Thu Sep 4 15:00:14 2014 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Thu, 4 Sep 2014 17:00:14 +0200 Subject: FTR: JVM Lang Summit presentation In-Reply-To: <54085B35.4030606@univ-mlv.fr> References: <4ADC415B-CD55-402A-AC3E-AC8A6C0535BA@oracle.com> <53E0F9DA.3030308@univ-mlv.fr> <1FC8A755-3C36-4B5C-84AE-5A080ADBE926@oracle.com> <53E54267.4030505@univ-mlv.fr> <7884990C-E602-4339-A557-1FDB98FBD3F7@oracle.com> <54060625.3010301@univ-mlv.fr> <884DF874-327D-4409-9DD4-4EB2FCB079CC@oracle.com> <540733A8.4060208@univ-mlv.fr> <081A4167-766C-4AAE-ABE8-309F1833E0B8@oracle.com> <540830E3.4060300@univ-mlv.fr> <6B29D8AC-4AF7-413F-8BE1-28F56262DE9D@oracle.com> <54085B35.4030606@univ-mlv.fr> Message-ID: <01A7281F-B8D9-4F2C-9673-3DB8C5801EE9@oracle.com> On Sep 4, 2014, at 2:29 PM, Remi Forax wrote: >> Not quite sure what you mean with the list example, but i have tested a static final instance of that RefFieldVarHandle class with calls to compareAndSet and multiple sub-classes of the receiver and value types. > > The same call site called with different arguments or several calls with different arguments. > The former may lead to profile pollution, not the later. I tried the former. >> Interestingly it seems for static final instances of AtomicReferenceFieldUpdater the type propagation may be failing. Perhaps this is due to certain other checks getting in the way, such as explicit class pointer checks. (Also i dunno if it is also because the class's methods are abstract.) > > I think, it's due to the fact that RefFieldVarHandle is declared in package java.lang.invoke which is special, the VM considers that the fields of classes of this package can not be changed by reflection thus the JIT can optimize through them. > Oh! real final fields! I did not realize there was special treatment beyond that for specifically annotated stuff. I cannot reproduce the optimizing effects outside of j.l.invoke. Do you know the area of hotspot where those optimizations are enforced? >> For the case of a poly sig method invocation the types are encoded at the call site, so for static final DHMs/VHs if the invocation is successful and gets inlined (which it should be forced to do when the calling method gets inlined) then it might be OK to remove the explicit cast on the value [*] > > poly sig is a lot of things, it's the sum of > - a special type calculation rule in javac > - a variable arity signature > - a special (two in fact) semantics of calling for the VM > Yes, i happen to be taking advantage of all of these so a VH can cover multiple shapes and value kinds. > in our case, we only need the first item plus invokedynamic to avoid to have to specify another specific semantics in the JLS, > that's why I think that poly sig is not the best vehicle for implementing type safe compareAndSet and friends. > But... going full circle... we still need a mechanism to signal how that indy is encoded... Paul. From christian.thalinger at oracle.com Thu Sep 4 17:24:02 2014 From: christian.thalinger at oracle.com (Christian Thalinger) Date: Thu, 4 Sep 2014 10:24:02 -0700 Subject: FTR: JVM Lang Summit presentation In-Reply-To: <01A7281F-B8D9-4F2C-9673-3DB8C5801EE9@oracle.com> References: <4ADC415B-CD55-402A-AC3E-AC8A6C0535BA@oracle.com> <53E0F9DA.3030308@univ-mlv.fr> <1FC8A755-3C36-4B5C-84AE-5A080ADBE926@oracle.com> <53E54267.4030505@univ-mlv.fr> <7884990C-E602-4339-A557-1FDB98FBD3F7@oracle.com> <54060625.3010301@univ-mlv.fr> <884DF874-327D-4409-9DD4-4EB2FCB079CC@oracle.com> <540733A8.4060208@univ-mlv.fr> <081A4167-766C-4AAE-ABE8-309F1833E0B8@oracle.com> <540830E3.4060300@univ-mlv.fr> <6B29D8AC-4AF7-413F-8BE1-28F56262DE9D@oracle.com> <54085B35.4030606@univ-mlv.fr> <01A7281F-B8D9-4F2C-9673-3DB8C5801EE9@oracle.com> Message-ID: On Sep 4, 2014, at 8:00 AM, Paul Sandoz wrote: > On Sep 4, 2014, at 2:29 PM, Remi Forax wrote: >>> Not quite sure what you mean with the list example, but i have tested a static final instance of that RefFieldVarHandle class with calls to compareAndSet and multiple sub-classes of the receiver and value types. >> >> The same call site called with different arguments or several calls with different arguments. >> The former may lead to profile pollution, not the later. > > I tried the former. > > >>> Interestingly it seems for static final instances of AtomicReferenceFieldUpdater the type propagation may be failing. Perhaps this is due to certain other checks getting in the way, such as explicit class pointer checks. (Also i dunno if it is also because the class's methods are abstract.) >> >> I think, it's due to the fact that RefFieldVarHandle is declared in package java.lang.invoke which is special, the VM considers that the fields of classes of this package can not be changed by reflection thus the JIT can optimize through them. >> > > Oh! real final fields! I did not realize there was special treatment beyond that for specifically annotated stuff. > > I cannot reproduce the optimizing effects outside of j.l.invoke. > > Do you know the area of hotspot where those optimizations are enforced? Search for: src/share/vm/runtime/globals.hpp 3827: experimental(bool, TrustFinalNonStaticFields, false, \ > > >>> For the case of a poly sig method invocation the types are encoded at the call site, so for static final DHMs/VHs if the invocation is successful and gets inlined (which it should be forced to do when the calling method gets inlined) then it might be OK to remove the explicit cast on the value [*] >> >> poly sig is a lot of things, it's the sum of >> - a special type calculation rule in javac >> - a variable arity signature >> - a special (two in fact) semantics of calling for the VM >> > > Yes, i happen to be taking advantage of all of these so a VH can cover multiple shapes and value kinds. > > >> in our case, we only need the first item plus invokedynamic to avoid to have to specify another specific semantics in the JLS, >> that's why I think that poly sig is not the best vehicle for implementing type safe compareAndSet and friends. >> > > But... going full circle... we still need a mechanism to signal how that indy is encoded... > > Paul. From paul.sandoz at oracle.com Thu Sep 4 19:27:11 2014 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Thu, 4 Sep 2014 21:27:11 +0200 Subject: FTR: JVM Lang Summit presentation In-Reply-To: References: <4ADC415B-CD55-402A-AC3E-AC8A6C0535BA@oracle.com> <53E0F9DA.3030308@univ-mlv.fr> <1FC8A755-3C36-4B5C-84AE-5A080ADBE926@oracle.com> <53E54267.4030505@univ-mlv.fr> <7884990C-E602-4339-A557-1FDB98FBD3F7@oracle.com> <54060625.3010301@univ-mlv.fr> <884DF874-327D-4409-9DD4-4EB2FCB079CC@oracle.com> <540733A8.4060208@univ-mlv.fr> <081A4167-766C-4AAE-ABE8-309F1833E0B8@oracle.com> <540830E3.4060300@univ-mlv.fr> <6B29D8AC-4AF7-413F-8BE1-28F56262DE9D@oracle.com> <54085B35.4030606@univ-mlv.fr> <01A7281F-B8D9-4F2C-9673-3DB8C5801EE9@oracle.com> Message-ID: On Sep 4, 2014, at 7:24 PM, Christian Thalinger wrote: >> Do you know the area of hotspot where those optimizations are enforced? > > Search for: > > src/share/vm/runtime/globals.hpp > 3827: experimental(bool, TrustFinalNonStaticFields, false, \ > Many thanks, got it (I should have followed the @Stable trail): static bool trust_final_non_static_fields(ciInstanceKlass* holder) { if (holder == NULL) return false; if (holder->name() == ciSymbol::java_lang_System()) // Never trust strangely unstable finals: System.out, etc. return false; // Even if general trusting is disabled, trust system-built closures in these packages. if (holder->is_in_package("java/lang/invoke") || holder->is_in_package("sun/invoke")) return true; return TrustFinalNonStaticFields; } I like the first comment :-) "// Never trust strangely unstable finals: System.out, etc.". Paul. From fab.parini at gmx.com Fri Sep 5 17:32:37 2014 From: fab.parini at gmx.com (Fabrizio Parini) Date: Fri, 5 Sep 2014 19:32:37 +0200 Subject: Operator overloading Message-ID: Hi, I would like to ask if there are good chances that Java will support operator overloading for value types when they become available. Regards, Fabrizio From brian.goetz at oracle.com Fri Sep 5 19:11:12 2014 From: brian.goetz at oracle.com (Brian Goetz) Date: Fri, 05 Sep 2014 15:11:12 -0400 Subject: Operator overloading In-Reply-To: References: Message-ID: <540A0AD0.3090606@oracle.com> In all practicality, I would not describe the chances as "good". (But I also would not describe it as something that is completely out of consideration for some future time.) On 9/5/2014 1:32 PM, Fabrizio Parini wrote: > Hi, > > I would like to ask if there are good chances that Java will support > operator overloading for value types when they become available. > > Regards, Fabrizio > From forax at univ-mlv.fr Fri Sep 5 19:11:22 2014 From: forax at univ-mlv.fr (Remi Forax) Date: Fri, 05 Sep 2014 21:11:22 +0200 Subject: Operator overloading In-Reply-To: References: Message-ID: <540A0ADA.4010604@univ-mlv.fr> On 09/05/2014 07:32 PM, Fabrizio Parini wrote: > Hi, > > I would like to ask if there are good chances that Java will support operator overloading for value types when they become available. > > Regards, > Fabrizio which kind and why ? R?mi From david.r.chase at oracle.com Fri Sep 5 19:22:20 2014 From: david.r.chase at oracle.com (David Chase) Date: Fri, 5 Sep 2014 15:22:20 -0400 Subject: Operator overloading In-Reply-To: <540A0ADA.4010604@univ-mlv.fr> References: <540A0ADA.4010604@univ-mlv.fr> Message-ID: <981ADBC7-DADA-46CA-A053-E3506C2E5D16@oracle.com> Remi, I can?t speak for him, but supposing the libraries for Arrays 2.0 turn out okay or better (it?s possible). Do you prefer a.set(times(plus(b,c),d) or a := (b+c)*d ? I put in ?:=? because I think overloading = might not work, since it already has a defined meaning for all object types. And the ?before? syntax might be a lot clunkier than that, what if it is a.set(times.apply(plus.apply(b,c),d) ? David On 2014-09-05, at 3:11 PM, Remi Forax wrote: > > On 09/05/2014 07:32 PM, Fabrizio Parini wrote: >> Hi, >> >> I would like to ask if there are good chances that Java will support operator overloading for value types when they become available. >> >> Regards, >> Fabrizio > > which kind and why ? > > R?mi > From forax at univ-mlv.fr Fri Sep 5 21:03:37 2014 From: forax at univ-mlv.fr (Remi Forax) Date: Fri, 05 Sep 2014 23:03:37 +0200 Subject: Operator overloading In-Reply-To: <981ADBC7-DADA-46CA-A053-E3506C2E5D16@oracle.com> References: <540A0ADA.4010604@univ-mlv.fr> <981ADBC7-DADA-46CA-A053-E3506C2E5D16@oracle.com> Message-ID: <540A2529.3040807@univ-mlv.fr> On 09/05/2014 09:22 PM, David Chase wrote: > Remi, I can?t speak for him, but supposing the libraries for Arrays 2.0 turn out okay or better (it?s possible). > Do you prefer > > a.set(times(plus(b,c),d) > > or > > a := (b+c)*d > > ? > > I put in ?:=? because I think overloading = might not work, since it already has a defined meaning for all object types. > > And the ?before? syntax might be a lot clunkier than that, what if it is > > a.set(times.apply(plus.apply(b,c),d) ? > > David Hi David, There are a lot of hazards associated with user defined operator overloading: - already existing operators use implicit conversions, I don't want user defined implicit conversions in Java. - operator are functions, not method I don't want virtual dispatch on operators in Java. - already existing operators have a default precedence and associativity for the parser I don't want user defined precedence rules in Java. - already existing operators are defined on immutable values I don't want rules about aliases and intermediary objects a la C++ in Java. if you solve all these issues you have my vote. R?mi > > On 2014-09-05, at 3:11 PM, Remi Forax wrote: > >> On 09/05/2014 07:32 PM, Fabrizio Parini wrote: >>> Hi, >>> >>> I would like to ask if there are good chances that Java will support operator overloading for value types when they become available. >>> >>> Regards, >>> Fabrizio >> which kind and why ? >> >> R?mi >> From paul.sandoz at oracle.com Mon Sep 8 17:17:21 2014 From: paul.sandoz at oracle.com (paul.sandoz at oracle.com) Date: Mon, 08 Sep 2014 17:17:21 +0000 Subject: hg: valhalla/valhalla/jdk: Support atomic add operations for int/long. For refs the operations will throw UnsupportedOperationException (currently wrapped in an Error, due to how the guard functions are currently structured). Message-ID: <201409081717.s88HHLK0011100@aojmv0008> Changeset: 968d2534b0ff Author: psandoz Date: 2014-09-08 19:14 +0200 URL: http://hg.openjdk.java.net/valhalla/valhalla/jdk/rev/968d2534b0ff Support atomic add operations for int/long. For refs the operations will throw UnsupportedOperationException (currently wrapped in an Error, due to how the guard functions are currently structured). ! src/java.base/share/classes/java/lang/invoke/ArrayHandle.java ! src/java.base/share/classes/java/lang/invoke/ArrayIntArrayHandle.java ! src/java.base/share/classes/java/lang/invoke/BaseVarHandle.java ! src/java.base/share/classes/java/lang/invoke/FieldHandle.java ! src/java.base/share/classes/java/lang/invoke/FieldInstanceIntFieldHandle.java ! src/java.base/share/classes/java/lang/invoke/FieldInstanceIntHandle.java ! src/java.base/share/classes/java/lang/invoke/FieldInstanceLongHandle.java ! src/java.base/share/classes/java/lang/invoke/OffHeapRegion.java ! src/java.base/share/classes/java/lang/invoke/VarForm.java ! src/java.base/share/classes/java/lang/invoke/VarHandle.java ! src/java.base/share/classes/java/lang/invoke/VarHandleGuards.java ! src/java.base/share/classes/java/lang/invoke/VarHandles.java ! test/java/lang/invoke/ArrayHandleTest.java ! test/java/lang/invoke/FieldHandleTest.java ! test/java/lang/invoke/OffHeapRegionHandleTest.java ! test/java/lang/invoke/VarHandleTest.java From brian.goetz at oracle.com Wed Sep 10 15:24:46 2014 From: brian.goetz at oracle.com (brian.goetz at oracle.com) Date: Wed, 10 Sep 2014 15:24:46 +0000 Subject: hg: valhalla/valhalla/jdk: Preliminary specializer support for generic methods Message-ID: <201409101524.s8AFOkmZ026584@aojmv0008> Changeset: 46ad6182986b Author: briangoetz Date: 2014-09-10 11:24 -0400 URL: http://hg.openjdk.java.net/valhalla/valhalla/jdk/rev/46ad6182986b Preliminary specializer support for generic methods + src/java.base/share/classes/java/lang/invoke/GenericMethodSpecializer.java ! src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java ! src/java.base/share/classes/valhalla/specializer/BytecodeMappingAttribute.java ! src/java.base/share/classes/valhalla/specializer/SignatureSpecializer.java ! src/java.base/share/classes/valhalla/specializer/Specialize.java ! src/java.base/share/classes/valhalla/specializer/Specializer.java ! src/java.base/share/classes/valhalla/specializer/TypeVariablesMapAttribute.java ! test/valhalla/test/valhalla/specializer/TwoBox.java ! test/valhalla/test/valhalla/specializer/TwoBoxTest.java From maurizio.cimadamore at oracle.com Wed Sep 10 21:13:07 2014 From: maurizio.cimadamore at oracle.com (maurizio.cimadamore at oracle.com) Date: Wed, 10 Sep 2014 21:13:07 +0000 Subject: hg: valhalla/valhalla/langtools: Fix bug in specialized method calls Message-ID: <201409102113.s8ALD84l022751@aojmv0008> Changeset: 8a6856f425fd Author: mcimadamore Date: 2014-09-10 22:12 +0100 URL: http://hg.openjdk.java.net/valhalla/valhalla/langtools/rev/8a6856f425fd Fix bug in specialized method calls * invokedType associated with specialized generic call should erase unspecialized type arguments ! src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java ! src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java ! src/jdk.compiler/share/classes/com/sun/tools/javac/comp/SpecializeTypes.java ! test/tools/javac/valhalla/typespec/items/tests/TestIndy.java From maurizio.cimadamore at oracle.com Wed Sep 10 21:15:14 2014 From: maurizio.cimadamore at oracle.com (maurizio.cimadamore at oracle.com) Date: Wed, 10 Sep 2014 21:15:14 +0000 Subject: hg: valhalla/valhalla/jdk: uncomment previously failing test Message-ID: <201409102115.s8ALFEKl023039@aojmv0008> Changeset: d4c0ede3ed28 Author: mcimadamore Date: 2014-09-10 22:14 +0100 URL: http://hg.openjdk.java.net/valhalla/valhalla/jdk/rev/d4c0ede3ed28 uncomment previously failing test ! test/valhalla/test/valhalla/specializer/TwoBoxTest.java From paul.sandoz at oracle.com Thu Sep 11 10:41:13 2014 From: paul.sandoz at oracle.com (paul.sandoz at oracle.com) Date: Thu, 11 Sep 2014 10:41:13 +0000 Subject: hg: valhalla/valhalla/jdk: 2 new changesets Message-ID: <201409111041.s8BAfEUs001911@aojmv0008> Changeset: 09704b3b091b Author: dl Date: 2014-09-01 13:33 +0200 URL: http://hg.openjdk.java.net/valhalla/valhalla/jdk/rev/09704b3b091b 8056249: Improve CompletableFuture resource usage Reviewed-by: psandoz, chegar, martin ! src/java.base/share/classes/java/util/concurrent/CompletableFuture.java ! src/java.base/share/classes/java/util/concurrent/CompletionStage.java Changeset: e13a08d8c54c Author: dl Date: 2014-09-05 10:54 +0200 URL: http://hg.openjdk.java.net/valhalla/valhalla/jdk/rev/e13a08d8c54c 8056248: Improve ForkJoin thread throttling Reviewed-by: psandoz, martin ! src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java ! src/java.base/share/classes/java/util/concurrent/ForkJoinTask.java ! src/java.base/share/classes/java/util/concurrent/ForkJoinWorkerThread.java From maurizio.cimadamore at oracle.com Thu Sep 11 17:52:24 2014 From: maurizio.cimadamore at oracle.com (maurizio.cimadamore at oracle.com) Date: Thu, 11 Sep 2014 17:52:24 +0000 Subject: hg: valhalla/valhalla/langtools: Bad signature specialization in generic specialized calls Message-ID: <201409111752.s8BHqOtk015247@aojmv0008> Changeset: ae56fa007104 Author: mcimadamore Date: 2014-09-11 18:45 +0100 URL: http://hg.openjdk.java.net/valhalla/valhalla/langtools/rev/ae56fa007104 Bad signature specialization in generic specialized calls * invokedType should mention the signature of the generic method seen as a member of the specialized class * a normalization step should take care of multiple re-specializations ! src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java ! src/jdk.compiler/share/classes/com/sun/tools/javac/comp/SpecializeTypes.java + test/tools/javac/valhalla/typespec/TestForwardRef.java + test/tools/javac/valhalla/typespec/items/tests/TestRespecialization.java From brian.goetz at oracle.com Thu Sep 11 18:47:29 2014 From: brian.goetz at oracle.com (brian.goetz at oracle.com) Date: Thu, 11 Sep 2014 18:47:29 +0000 Subject: hg: valhalla/valhalla/jdk: Perform local-variable-number shuffling in presence of specialization to long or double Message-ID: <201409111847.s8BIlUJS023236@aojmv0008> Changeset: 92f754fc21d5 Author: briangoetz Date: 2014-09-11 14:47 -0400 URL: http://hg.openjdk.java.net/valhalla/valhalla/jdk/rev/92f754fc21d5 Perform local-variable-number shuffling in presence of specialization to long or double ! src/java.base/share/classes/valhalla/specializer/Specializer.java + test/valhalla/test/valhalla/specializer/MixedTypesTest.java From brian.goetz at oracle.com Thu Sep 11 18:51:32 2014 From: brian.goetz at oracle.com (brian.goetz at oracle.com) Date: Thu, 11 Sep 2014 18:51:32 +0000 Subject: hg: valhalla/valhalla/jdk: Restore missing import Message-ID: <201409111851.s8BIpWa2024085@aojmv0008> Changeset: bc9fae81d774 Author: briangoetz Date: 2014-09-11 14:51 -0400 URL: http://hg.openjdk.java.net/valhalla/valhalla/jdk/rev/bc9fae81d774 Restore missing import ! test/valhalla/test/valhalla/specializer/MixedTypesTest.java From maurizio.cimadamore at oracle.com Fri Sep 12 13:55:03 2014 From: maurizio.cimadamore at oracle.com (maurizio.cimadamore at oracle.com) Date: Fri, 12 Sep 2014 13:55:03 +0000 Subject: hg: valhalla/valhalla/langtools: Fix bugs in generic specialized method call type-checking Message-ID: <201409121355.s8CDt3nK001255@aojmv0008> Changeset: 3cf735859c28 Author: mcimadamore Date: 2014-09-12 14:45 +0100 URL: http://hg.openjdk.java.net/valhalla/valhalla/langtools/rev/3cf735859c28 Fix bugs in generic specialized method call type-checking * explicit specialized generic method calls are not specialized in the bytecode * treatment of boxed target-type in specialized method calls leads to spurious errors ! src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java ! src/jdk.compiler/share/classes/com/sun/tools/javac/comp/SpecializeTypes.java ! test/tools/javac/valhalla/typespec/Inference01.java + test/tools/javac/valhalla/typespec/Inference04.java ! test/tools/javac/valhalla/typespec/items/tests/TestIndy.java From paul.sandoz at oracle.com Fri Sep 12 14:58:33 2014 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Fri, 12 Sep 2014 16:58:33 +0200 Subject: Updates j.u.c patch and added loop results Re: VarHandle prototype pushed In-Reply-To: <372511FA-0A78-4488-B402-19EB658419EB@oracle.com> References: <372511FA-0A78-4488-B402-19EB658419EB@oracle.com> Message-ID: <41F956AE-BD47-481A-B21B-5F78BDD7CFD4@oracle.com> Hi, I recently: - merged 9 updates to CompletableFuture and F/J. - updated the JUC patch converting many j.u.c classes to use VarHandle http://cr.openjdk.java.net/~psandoz/varhandles/jdk-varhandle-juc.patch/webrev/ (Still have to do CHM, which i hope does not introduce a bootstrap issue, there is certainly one if MHs are used.) - uploaded some 166 loop test results run on Dell laptop with an Intel Core i5-2520M CPU @ 2.50GHz x 4. All CPUs were frozen at 2GHz with power management disabled. http://cr.openjdk.java.net/~psandoz/varhandles/valhalla-unsafe.166-loops.11-09-2014.txt http://cr.openjdk.java.net/~psandoz/varhandles/valhalla-vhs-no-cast.166-loops.12-09-2014.txt http://cr.openjdk.java.net/~psandoz/varhandles/valhalla-vhs.166-loops.11-09-2014.txt Have yet to do any analysis of the results. Paul. On Aug 7, 2014, at 10:31 AM, Paul Sandoz wrote: > Hi, > > I have just pushed the VarHandle prototype. More details can be found here: > > http://cr.openjdk.java.net/~psandoz/varhandles/VarHandle-0.1.md > http://cr.openjdk.java.net/~psandoz/varhandles/jvmls14-varHandles.pdf > > Hopefully it won't cause too much disturbance in the "force", but if anyone pulled in-between my pushes to jdk, langtools and hotspot then one will need pull again so everything is in sync. Also, it is unlikely to step on the value type/specialization area as the changes to langtools/hotspot are focused on areas particular to polymorphic signature methods. > > This prototype is sufficient to play around with the API, validate performance and find issues, but it's still very much work in progress. > > I have yet to push a patch to update certain j.u.c classes to replace Unsafe with VarHandle [1]. I am pondering whether to have separate renamed classes, which is nice for a side-to-side comparison in the same code base, but would force test code (e.g. 166 loops tests) to be updated. > > Paul. > > [1] http://cr.openjdk.java.net/~psandoz/varhandles/jdk-varhandle-juc.patch/webrev/ From paul.govereau at oracle.com Sat Sep 13 16:26:50 2014 From: paul.govereau at oracle.com (Paul Govereau) Date: Sat, 13 Sep 2014 12:26:50 -0400 Subject: Generic sort Message-ID: <5414704A.8040906@oracle.com> Hello, I have been trying to write a fully generic SortedArrayList, but I don't see a good way to implement sort. The difficulty has to do with comparison. I am assuming that, like objects but unlike the primitive types, value types will not have an implicit ordering. So, objects and values must support an interface for comparison. For the primitives, the bytecode needed for comparison is not easily synthesized (e.g. do you choose fcmpl or fcmpg?). It seems that we need something like this: class SortedArrayList { T[] array; ... > int cmp(T x, T y) { try return x.compareTo(y); catch (NullPointerException e) { return -1; // similar to fcmpl } } > int cmp(T x, T y) { return x.comapreTo(y); // no null pointers. } int cmp(T x, T y) { return x < y; } // if_icmplt int cmp(T x, T y) { return x < y; } // lcmp; iflt int cmp(T x, T y) { return x < y; } // fcmpl; iflt int cmp(T x, T y) { return x < y; } // dcmpl; iflt ... } Note, in this case SortedArrayList is not inhabited. Do we think that the programmer must give an implementation for Object that raises exceptions, or do we think the type system will disallow instantiation with Object? Here is another example along the same lines. class Group { ... > T add(T x, T y) { return x.add(y); } // invoke* > T add(T x, T y) { return x.add(y); } // vinvoke* T add(T x, T y) { return x+y; } // iadd/ladd/fadd/dadd } Group OK reference type Group OK value type Group OK primitive Group ?? not OK Paul From joe.darcy at oracle.com Sat Sep 13 16:53:07 2014 From: joe.darcy at oracle.com (Joe Darcy) Date: Sat, 13 Sep 2014 09:53:07 -0700 Subject: Generic sort In-Reply-To: <5414704A.8040906@oracle.com> References: <5414704A.8040906@oracle.com> Message-ID: <54147673.3030301@oracle.com> Hello, On the topic of sorting floating-point values, note that the < operation does not impose a total ordering on floating-point values, primarily because of NaN. There is also the smaller issue of -0.0 being == to +0.0 but the values being distinguishable. A method like java.lang.Double.compare will serve your sorting needs though. HTH, -Joe On 9/13/2014 9:26 AM, Paul Govereau wrote: > Hello, > > I have been trying to write a fully generic SortedArrayList, > but I don't see a good way to implement sort. The difficulty has to do > with comparison. I am assuming that, like objects but unlike the > primitive types, value types will not have an implicit ordering. So, > objects and values must support an interface for comparison. For the > primitives, the bytecode needed for comparison is not easily > synthesized (e.g. do you choose fcmpl or fcmpg?). > > It seems that we need something like this: > > class SortedArrayList { > T[] array; > ... > > > > int cmp(T x, T y) { > try return x.compareTo(y); > catch (NullPointerException e) { > return -1; // similar to fcmpl > } > } > > > > int cmp(T x, T y) { > return x.comapreTo(y); // no null pointers. > } > > > int cmp(T x, T y) { return x < y; } // if_icmplt > > int cmp(T x, T y) { return x < y; } // lcmp; iflt > > int cmp(T x, T y) { return x < y; } // fcmpl; iflt > > int cmp(T x, T y) { return x < y; } // dcmpl; iflt > > ... > } > > Note, in this case SortedArrayList is not inhabited. Do we > think that the programmer must give an implementation for Object that > raises exceptions, or do we think the type system will disallow > instantiation with Object? > > Here is another example along the same lines. > > class Group { > ... > > > T add(T x, T y) { return x.add(y); } // invoke* > > > > T add(T x, T y) { return x.add(y); } // vinvoke* > > > T add(T x, T y) { return x+y; } // iadd/ladd/fadd/dadd > } > > Group OK reference type > Group OK value type > Group OK primitive > Group ?? not OK > > Paul From brian.goetz at oracle.com Sat Sep 13 20:42:54 2014 From: brian.goetz at oracle.com (Brian Goetz) Date: Sat, 13 Sep 2014 16:42:54 -0400 Subject: Generic sort In-Reply-To: <5414704A.8040906@oracle.com> References: <5414704A.8040906@oracle.com> Message-ID: <5414AC4E.10100@oracle.com> Let's ignore for now whether conditional methods can be conditioned on "T extends U". (Being able to do so adds complexity to the meet rule, among other issues.) It is likely that common operations like comparison or array creation can be "pre-peeled" into library code so this logic does not have to be duplicated in user code (which just pushes the problem into our code.) Existing sorted data structures do not impose the T-extends-Comparable constraint; they just risk throwing CCE, or require that you provide a Comparator. The latter route might be better; just require a Comparator all the time. On 9/13/2014 12:26 PM, Paul Govereau wrote: > Hello, > > I have been trying to write a fully generic SortedArrayList, but > I don't see a good way to implement sort. The difficulty has to do with > comparison. I am assuming that, like objects but unlike the primitive > types, value types will not have an implicit ordering. So, objects and > values must support an interface for comparison. For the primitives, the > bytecode needed for comparison is not easily synthesized (e.g. do you > choose fcmpl or fcmpg?). > > It seems that we need something like this: > > class SortedArrayList { > T[] array; > ... > > > > int cmp(T x, T y) { > try return x.compareTo(y); > catch (NullPointerException e) { > return -1; // similar to fcmpl > } > } > > > > int cmp(T x, T y) { > return x.comapreTo(y); // no null pointers. > } > > > int cmp(T x, T y) { return x < y; } // if_icmplt > > int cmp(T x, T y) { return x < y; } // lcmp; iflt > > int cmp(T x, T y) { return x < y; } // fcmpl; iflt > > int cmp(T x, T y) { return x < y; } // dcmpl; iflt > > ... > } > > Note, in this case SortedArrayList is not inhabited. Do we think > that the programmer must give an implementation for Object that raises > exceptions, or do we think the type system will disallow instantiation > with Object? > > Here is another example along the same lines. > > class Group { > ... > > > T add(T x, T y) { return x.add(y); } // invoke* > > > > T add(T x, T y) { return x.add(y); } // vinvoke* > > > T add(T x, T y) { return x+y; } // iadd/ladd/fadd/dadd > } > > Group OK reference type > Group OK value type > Group OK primitive > Group ?? not OK > > Paul From paul.govereau at oracle.com Sat Sep 13 22:29:58 2014 From: paul.govereau at oracle.com (Paul Govereau) Date: Sat, 13 Sep 2014 18:29:58 -0400 Subject: Generic sort In-Reply-To: <5414AC4E.10100@oracle.com> References: <5414704A.8040906@oracle.com> <5414AC4E.10100@oracle.com> Message-ID: <5414C566.9050305@oracle.com> OK, to be clear, I think you are saying that yes, the programmer must provide an implementation that throws exceptions. This may be in SortedArrayList or through a library class like Comparator. I think you are also saying that this would be the case for the value type layer as well. That is, something like: SortedArrayList.cmp(a,b) can throw a CCE where Complex is a value type. This seems to imply we need byte code instructions: vinstanceof and vcheckcast. This seems strange, what am I missing? Paul On 09/13/2014 04:42 PM, Brian Goetz wrote: > Let's ignore for now whether conditional methods can be conditioned on > "T extends U". (Being able to do so adds complexity to the meet rule, > among other issues.) > > It is likely that common operations like comparison or array creation > can be "pre-peeled" into library code so this logic does not have to be > duplicated in user code (which just pushes the problem into our code.) > > Existing sorted data structures do not impose the T-extends-Comparable > constraint; they just risk throwing CCE, or require that you provide a > Comparator. The latter route might be better; just require a > Comparator all the time. > > On 9/13/2014 12:26 PM, Paul Govereau wrote: >> Hello, >> >> I have been trying to write a fully generic SortedArrayList, but >> I don't see a good way to implement sort. The difficulty has to do with >> comparison. I am assuming that, like objects but unlike the primitive >> types, value types will not have an implicit ordering. So, objects and >> values must support an interface for comparison. For the primitives, the >> bytecode needed for comparison is not easily synthesized (e.g. do you >> choose fcmpl or fcmpg?). >> >> It seems that we need something like this: >> >> class SortedArrayList { >> T[] array; >> ... >> >> > >> int cmp(T x, T y) { >> try return x.compareTo(y); >> catch (NullPointerException e) { >> return -1; // similar to fcmpl >> } >> } >> >> > >> int cmp(T x, T y) { >> return x.comapreTo(y); // no null pointers. >> } >> >> >> int cmp(T x, T y) { return x < y; } // if_icmplt >> >> int cmp(T x, T y) { return x < y; } // lcmp; iflt >> >> int cmp(T x, T y) { return x < y; } // fcmpl; iflt >> >> int cmp(T x, T y) { return x < y; } // dcmpl; iflt >> >> ... >> } >> >> Note, in this case SortedArrayList is not inhabited. Do we think >> that the programmer must give an implementation for Object that raises >> exceptions, or do we think the type system will disallow instantiation >> with Object? >> >> Here is another example along the same lines. >> >> class Group { >> ... >> > >> T add(T x, T y) { return x.add(y); } // invoke* >> >> > >> T add(T x, T y) { return x.add(y); } // vinvoke* >> >> >> T add(T x, T y) { return x+y; } // iadd/ladd/fadd/dadd >> } >> >> Group OK reference type >> Group OK value type >> Group OK primitive >> Group ?? not OK >> >> Paul From forax at univ-mlv.fr Sat Sep 13 23:34:10 2014 From: forax at univ-mlv.fr (Remi Forax) Date: Sun, 14 Sep 2014 01:34:10 +0200 Subject: Generic sort In-Reply-To: <5414C566.9050305@oracle.com> References: <5414704A.8040906@oracle.com> <5414AC4E.10100@oracle.com> <5414C566.9050305@oracle.com> Message-ID: <5414D472.3040104@univ-mlv.fr> On 09/14/2014 12:29 AM, Paul Govereau wrote: > OK, to be clear, I think you are saying that yes, the programmer must > provide an implementation that throws exceptions. This may be in > SortedArrayList or through a library class like Comparator. > > I think you are also saying that this would be the case for the value > type layer as well. That is, something like: > > SortedArrayList.cmp(a,b) > > can throw a CCE where Complex is a value type. This seems to imply we > need byte code instructions: vinstanceof and vcheckcast. > > This seems strange, what am I missing? > > Paul The idea is more that SortedArrayList is written like this. public class SortedArrayList { private /*true*/ final Comparator comparator; public SortedArrayList(Comparator comparator) { this.comparator = Objects.requireNonNull(comparator); } ... } with a String: new SortedArrayList(String::compareTo) with an int new SortedArrayList(Integer::compare) if T is an object and the comparator is not able to compare T with itselft, the comparator code (exactly either the bridge inserted by the compiler or the code of the lambda proxy) will throw a CCE. BTW, what Comparator means if T is declared any T ? Is it illegal because Comparator should use declaration site variance ? R?mi > > On 09/13/2014 04:42 PM, Brian Goetz wrote: >> Let's ignore for now whether conditional methods can be conditioned on >> "T extends U". (Being able to do so adds complexity to the meet rule, >> among other issues.) >> >> It is likely that common operations like comparison or array creation >> can be "pre-peeled" into library code so this logic does not have to be >> duplicated in user code (which just pushes the problem into our code.) >> >> Existing sorted data structures do not impose the T-extends-Comparable >> constraint; they just risk throwing CCE, or require that you provide a >> Comparator. The latter route might be better; just require a >> Comparator all the time. >> >> On 9/13/2014 12:26 PM, Paul Govereau wrote: >>> Hello, >>> >>> I have been trying to write a fully generic SortedArrayList, but >>> I don't see a good way to implement sort. The difficulty has to do with >>> comparison. I am assuming that, like objects but unlike the primitive >>> types, value types will not have an implicit ordering. So, objects and >>> values must support an interface for comparison. For the primitives, >>> the >>> bytecode needed for comparison is not easily synthesized (e.g. do you >>> choose fcmpl or fcmpg?). >>> >>> It seems that we need something like this: >>> >>> class SortedArrayList { >>> T[] array; >>> ... >>> >>> > >>> int cmp(T x, T y) { >>> try return x.compareTo(y); >>> catch (NullPointerException e) { >>> return -1; // similar to fcmpl >>> } >>> } >>> >>> > >>> int cmp(T x, T y) { >>> return x.comapreTo(y); // no null pointers. >>> } >>> >>> >>> int cmp(T x, T y) { return x < y; } // if_icmplt >>> >>> int cmp(T x, T y) { return x < y; } // lcmp; iflt >>> >>> int cmp(T x, T y) { return x < y; } // fcmpl; iflt >>> >>> int cmp(T x, T y) { return x < y; } // dcmpl; iflt >>> >>> ... >>> } >>> >>> Note, in this case SortedArrayList is not inhabited. Do we >>> think >>> that the programmer must give an implementation for Object that raises >>> exceptions, or do we think the type system will disallow instantiation >>> with Object? >>> >>> Here is another example along the same lines. >>> >>> class Group { >>> ... >>> > >>> T add(T x, T y) { return x.add(y); } // invoke* >>> >>> > >>> T add(T x, T y) { return x.add(y); } // vinvoke* >>> >>> >>> T add(T x, T y) { return x+y; } // iadd/ladd/fadd/dadd >>> } >>> >>> Group OK reference type >>> Group OK value type >>> Group OK primitive >>> Group ?? not OK >>> >>> Paul From brian.goetz at oracle.com Sun Sep 14 01:39:50 2014 From: brian.goetz at oracle.com (Brian Goetz) Date: Sat, 13 Sep 2014 21:39:50 -0400 Subject: Generic sort In-Reply-To: <5414C566.9050305@oracle.com> References: <5414704A.8040906@oracle.com> <5414AC4E.10100@oracle.com> <5414C566.9050305@oracle.com> Message-ID: <5414F1E6.90709@oracle.com> > can throw a CCE where Complex is a value type. This seems to imply we > need byte code instructions: vinstanceof and vcheckcast. > > This seems strange, what am I missing? Some bytecodes need to be v-ified (xreturn, xload), but others (dup) need not because they are intrinsically polymorphic. In the middle are those that take type descriptors as operands (checkcast); if we expand the set of type descriptors to include q-types, you need not v-ify the bytecode, you can just expand the range of operands. From john.r.rose at oracle.com Sun Sep 14 03:03:39 2014 From: john.r.rose at oracle.com (John Rose) Date: Sat, 13 Sep 2014 20:03:39 -0700 Subject: Generic sort In-Reply-To: <5414704A.8040906@oracle.com> References: <5414704A.8040906@oracle.com> Message-ID: <571F53EE-32C4-486C-A2E5-0330D129F62D@oracle.com> On Sep 13, 2014, at 9:26 AM, Paul Govereau wrote: > Hello, > > I have been trying to write a fully generic SortedArrayList, but I don't see a good way to implement sort. The difficulty has to do with comparison. I am assuming that, like objects but unlike the primitive types, value types will not have an implicit ordering. So, objects and values must support an interface for comparison. This is contemplated in the VT proposal; see occurrences of Comparable. The bridge from a VT to an interface is about the same as from a class to the same interface. In both cases, if you have a concrete type, you invoke methods on the concrete type, not the interface. The missing bit is to supply a canonical VT-style box for each primitive. > For the primitives, the bytecode needed for comparison is not easily synthesized (e.g. do you choose fcmpl or fcmpg?). I would say (as Joe suggests) look to the current wrapper types for guidance. > It seems that we need something like this: > > class SortedArrayList { > T[] array; > ... > > > > int cmp(T x, T y) { > try return x.compareTo(y); > catch (NullPointerException e) { > return -1; // similar to fcmpl > } > } > > > > int cmp(T x, T y) { > return x.comapreTo(y); // no null pointers. > } When I see this, my first thought is why do we need 'where' clauses for this use case? Is the possibility of a RuntimeException enough to break parametric polymorphism? I don't see why. If null handling is necessary (beyond NPEs which can be swept under the rug), push that down into a 'where' clause: static boolean isNull(T x) { return x == null; } static boolean isNull(T x) { return false; } ...better yet, since null processing is wired into the VM, allow "x == null" in polymorphic code (given 'any x'), and define it to mean false when T is a non-reference. This is logically true. It also meets the spirit of the polymorphic template: "x could be a reference, in some instances, so it makes sense to ask if it is null, at least sometimes". > > > int cmp(T x, T y) { return x < y; } // if_icmplt > > int cmp(T x, T y) { return x < y; } // lcmp; iflt > > int cmp(T x, T y) { return x < y; } // fcmpl; iflt > > int cmp(T x, T y) { return x < y; } // dcmpl; iflt This stuff should all be mediated by wrappers. Put another way, it doesn't belong in SortedArray, but in some global definitions which connect primitive types to Comparable. > ... > } > > Note, in this case SortedArrayList is not inhabited. Do we think that the programmer must give an implementation for Object that raises exceptions, or do we think the type system will disallow instantiation with Object? It should be: class SortedArrayList> { Then the question does not arise. > Here is another example along the same lines. > > class Group { > ... > > > T add(T x, T y) { return x.add(y); } // invoke* > > > > T add(T x, T y) { return x.add(y); } // vinvoke* > > > T add(T x, T y) { return x+y; } // iadd/ladd/fadd/dadd > } > > Group OK reference type > Group OK value type > Group OK primitive > Group ?? not OK Should be Group. To me, this is an argument for primitive boxes to implement Number (which they happen to even today) and for Number to implement a value-compatible interface Numeric. (BTW, character and boolean don't exactly add, nor are they Numbers. "prim" is not the right type selector or type bound here.) ? John From john.r.rose at oracle.com Sun Sep 14 03:04:26 2014 From: john.r.rose at oracle.com (John Rose) Date: Sat, 13 Sep 2014 20:04:26 -0700 Subject: Generic sort In-Reply-To: <5414AC4E.10100@oracle.com> References: <5414704A.8040906@oracle.com> <5414AC4E.10100@oracle.com> Message-ID: <8CA05B80-3C9A-4A26-9B3C-6864D7618DC3@oracle.com> On Sep 13, 2014, at 1:42 PM, Brian Goetz wrote: > It is likely that common operations like comparison or array creation can be "pre-peeled" into library code so this logic does not have to be duplicated in user code (which just pushes the problem into our code.) Right, and pre-eminently in new value-compatible box types. ? John From john.r.rose at oracle.com Sun Sep 14 03:07:43 2014 From: john.r.rose at oracle.com (John Rose) Date: Sat, 13 Sep 2014 20:07:43 -0700 Subject: Generic sort In-Reply-To: <5414C566.9050305@oracle.com> References: <5414704A.8040906@oracle.com> <5414AC4E.10100@oracle.com> <5414C566.9050305@oracle.com> Message-ID: On Sep 13, 2014, at 3:29 PM, Paul Govereau wrote: > This seems to imply we need byte code instructions: vinstanceof and vcheckcast. > > This seems strange, what am I missing? There are two ways to think about this. The simplest is to box first and then ask questions. If the template instance is of a non-reference, box it and then apply the reference operation. This leads to a refinement, or optimization: Usually or always, the parameter type is known exactly during instantiation. In that case, the reference query can be constant folded. BTW, "x == null" is a reference query. It can be constant folded by observing that a boxed prim or val is never null. ? John From john.r.rose at oracle.com Sun Sep 14 03:09:09 2014 From: john.r.rose at oracle.com (John Rose) Date: Sat, 13 Sep 2014 20:09:09 -0700 Subject: Generic sort In-Reply-To: <5414F1E6.90709@oracle.com> References: <5414704A.8040906@oracle.com> <5414AC4E.10100@oracle.com> <5414C566.9050305@oracle.com> <5414F1E6.90709@oracle.com> Message-ID: On Sep 13, 2014, at 6:39 PM, Brian Goetz wrote: >> can throw a CCE where Complex is a value type. This seems to imply we >> need byte code instructions: vinstanceof and vcheckcast. >> >> This seems strange, what am I missing? > > Some bytecodes need to be v-ified (xreturn, xload), but others (dup) need not because they are intrinsically polymorphic. In the middle are those that take type descriptors as operands (checkcast); if we expand the set of type descriptors to include q-types, you need not v-ify the bytecode, you can just expand the range of operands. Yes; there may be bytecodes that work directly with the Q-types which would be preferable to boxing and then asking L-type questions. But I think there is great conceptual power in the "box first" approach. ? John From brian.goetz at oracle.com Sun Sep 14 14:48:23 2014 From: brian.goetz at oracle.com (Brian Goetz) Date: Sun, 14 Sep 2014 10:48:23 -0400 Subject: Generic sort In-Reply-To: <571F53EE-32C4-486C-A2E5-0330D129F62D@oracle.com> References: <5414704A.8040906@oracle.com> <571F53EE-32C4-486C-A2E5-0330D129F62D@oracle.com> Message-ID: <5415AAB7.3070405@oracle.com> > This stuff should all be mediated by wrappers. Put another way, it doesn't belong in SortedArray, but in some global definitions which connect primitive types to Comparable. This is what I mean "pre-peeled methods"; somewhere in the library, there is support for isNull, newArray, compare, etc. From forax at univ-mlv.fr Thu Sep 18 09:20:09 2014 From: forax at univ-mlv.fr (Remi Forax) Date: Thu, 18 Sep 2014 11:20:09 +0200 Subject: FTR: JVM Lang Summit presentation In-Reply-To: <01A7281F-B8D9-4F2C-9673-3DB8C5801EE9@oracle.com> References: <4ADC415B-CD55-402A-AC3E-AC8A6C0535BA@oracle.com> <53E0F9DA.3030308@univ-mlv.fr> <1FC8A755-3C36-4B5C-84AE-5A080ADBE926@oracle.com> <53E54267.4030505@univ-mlv.fr> <7884990C-E602-4339-A557-1FDB98FBD3F7@oracle.com> <54060625.3010301@univ-mlv.fr> <884DF874-327D-4409-9DD4-4EB2FCB079CC@oracle.com> <540733A8.4060208@univ-mlv.fr> <081A4167-766C-4AAE-ABE8-309F1833E0B8@oracle.com> <540830E3.4060300@univ-mlv.fr> <6B29D8AC-4AF7-413F-8BE1-28F56262DE9D@oracle.com> <54085B35.4030606@univ-mlv.fr> <01A7281F-B8D9-4F2C-9673-3DB8C5801EE9@oracle.com> Message-ID: <541AA3C9.4030302@univ-mlv.fr> On 09/04/2014 05:00 PM, Paul Sandoz wrote: > On Sep 4, 2014, at 2:29 PM, Remi Forax wrote: >>> Not quite sure what you mean with the list example, but i have tested a static final instance of that RefFieldVarHandle class with calls to compareAndSet and multiple sub-classes of the receiver and value types. >> The same call site called with different arguments or several calls with different arguments. >> The former may lead to profile pollution, not the later. > I tried the former. > [...] > > >>> For the case of a poly sig method invocation the types are encoded at the call site, so for static final DHMs/VHs if the invocation is successful and gets inlined (which it should be forced to do when the calling method gets inlined) then it might be OK to remove the explicit cast on the value [*] >> poly sig is a lot of things, it's the sum of >> - a special type calculation rule in javac >> - a variable arity signature >> - a special (two in fact) semantics of calling for the VM >> > Yes, i happen to be taking advantage of all of these so a VH can cover multiple shapes and value kinds. as i said earlier to John, we don't really need to have one code with multiple shapes, here what we want is to have type specialization but we will not have it for 9 so we can use overloads as we usually do to support strawman type specialization. also note that we only need overloads for signature, if we use indy, we can have several overloads but one implementation. > > >> in our case, we only need the first item plus invokedynamic to avoid to have to specify another specific semantics in the JLS, >> that's why I think that poly sig is not the best vehicle for implementing type safe compareAndSet and friends. >> > But... going full circle... we still need a mechanism to signal how that indy is encoded... yes, you need an annotation and a meta annotation to specify the bootstrap method class and the bsm name. > > Paul. R?mi From maurizio.cimadamore at oracle.com Fri Sep 19 10:07:00 2014 From: maurizio.cimadamore at oracle.com (maurizio.cimadamore at oracle.com) Date: Fri, 19 Sep 2014 10:07:00 +0000 Subject: hg: valhalla/valhalla/langtools: Generate bridges to non-generic super calls from generic specializable methods. Message-ID: <201409191007.s8JA71DJ017066@aojmv0008> Changeset: 1d8d72072928 Author: mcimadamore Date: 2014-09-19 11:05 +0100 URL: http://hg.openjdk.java.net/valhalla/valhalla/langtools/rev/1d8d72072928 Generate bridges to non-generic super calls from generic specializable methods. ! src/jdk.compiler/share/classes/com/sun/tools/javac/comp/SpecializeTypes.java + test/tools/javac/valhalla/typespec/TestSuperBridges.java From john.r.rose at oracle.com Fri Sep 19 17:13:46 2014 From: john.r.rose at oracle.com (John Rose) Date: Fri, 19 Sep 2014 10:13:46 -0700 Subject: FTR: JVM Lang Summit presentation In-Reply-To: <541AA3C9.4030302@univ-mlv.fr> References: <4ADC415B-CD55-402A-AC3E-AC8A6C0535BA@oracle.com> <53E0F9DA.3030308@univ-mlv.fr> <1FC8A755-3C36-4B5C-84AE-5A080ADBE926@oracle.com> <53E54267.4030505@univ-mlv.fr> <7884990C-E602-4339-A557-1FDB98FBD3F7@oracle.com> <54060625.3010301@univ-mlv.fr> <884DF874-327D-4409-9DD4-4EB2FCB079CC@oracle.com> <540733A8.4060208@univ-mlv.fr> <081A4167-766C-4AAE-ABE8-309F1833E0B8@oracle.com> <540830E3.4060300@univ-mlv.fr> <6B29D8AC-4AF7-413F-8BE1-28F56262DE9D@oracle.com> <54085B35.4030606@univ-mlv.fr> <01A7281F-B8D9-4F2C-9673-3DB8C5801EE9@oracle.com> <541AA3C9.4030302@univ-mlv.fr> Message-ID: On Sep 18, 2014, at 2:20 AM, Remi Forax wrote: > also note that we only need overloads for signature, if we use indy, we can have > several overloads but one implementation. That's why I have been casting about for some way to express indy-binding for VarHandle APIs (instead of the sig-poly binding of VHs in Paul's prototype). Indy provides caller-side signature polymorphism, and leaves the binding up to a factory somewhere, which might be as simple as a MH.asType call to take the polymorphism away, or could be something fancier. I also think that the asType transform is a good starting point for expressing instantiation of parametric polymorphism. ? John From forax at univ-mlv.fr Fri Sep 19 21:58:48 2014 From: forax at univ-mlv.fr (Remi Forax) Date: Fri, 19 Sep 2014 23:58:48 +0200 Subject: FTR: JVM Lang Summit presentation In-Reply-To: References: <4ADC415B-CD55-402A-AC3E-AC8A6C0535BA@oracle.com> <53E0F9DA.3030308@univ-mlv.fr> <1FC8A755-3C36-4B5C-84AE-5A080ADBE926@oracle.com> <53E54267.4030505@univ-mlv.fr> <7884990C-E602-4339-A557-1FDB98FBD3F7@oracle.com> <54060625.3010301@univ-mlv.fr> <884DF874-327D-4409-9DD4-4EB2FCB079CC@oracle.com> <540733A8.4060208@univ-mlv.fr> <081A4167-766C-4AAE-ABE8-309F1833E0B8@oracle.com> <540830E3.4060300@univ-mlv.fr> <6B29D8AC-4AF7-413F-8BE1-28F56262DE9D@oracle.com> <54085B35.4030606@univ-mlv.fr> <01A7281F-B8D9-4F2C-9673-3DB8C5801EE9@oracle.com> <541AA3C9.4030302@univ-mlv.fr> Message-ID: <541CA718.1050400@univ-mlv.fr> On 09/19/2014 07:13 PM, John Rose wrote: > On Sep 18, 2014, at 2:20 AM, Remi Forax > wrote: > >> also note that we only need overloads for signature, if we use indy, >> we can have >> several overloads but one implementation. > > That's why I have been casting about for some way to express > indy-binding for VarHandle APIs (instead of the sig-poly binding of > VHs in Paul's prototype). An annotation on the method declaration. A meta-annotation on the annotation that specify the BSM. Meta-protocol: a call to an annotated method is translated to an invokedynamic, the descriptor of indy is inferred from the type of the arguments (like with a polymorphic signature), the return type is the return type of the annotated method (may be a cast can override this behavior). If the annotated method is not abstract, the annotated method is sent as a bootstrap argument. > > Indy provides caller-side signature polymorphism, and leaves the > binding up to a factory somewhere, which might be as simple as a > MH.asType call to take the polymorphism away, or could be something > fancier. > > I also think that the asType transform is a good starting point for > expressing instantiation of parametric polymorphism. Let see, the JIT will prefer the types propagated from the callsite to the profile types. The compiler will have to use v-opcodes (opcodes depend on either the types on stack or the type of the local variables). There is still the problem of opcodes that embed specified types like getfield/invoke*, instanceof, checkcast, anewarrray or worst a lambda that use a parametrized functional interfaces (in that case, the BSM args of invokedynamic also need to be specialized). > > ? John R?mi From paul.sandoz at oracle.com Fri Sep 19 22:06:25 2014 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Sat, 20 Sep 2014 00:06:25 +0200 Subject: FTR: JVM Lang Summit presentation In-Reply-To: <541AA3C9.4030302@univ-mlv.fr> References: <4ADC415B-CD55-402A-AC3E-AC8A6C0535BA@oracle.com> <53E0F9DA.3030308@univ-mlv.fr> <1FC8A755-3C36-4B5C-84AE-5A080ADBE926@oracle.com> <53E54267.4030505@univ-mlv.fr> <7884990C-E602-4339-A557-1FDB98FBD3F7@oracle.com> <54060625.3010301@univ-mlv.fr> <884DF874-327D-4409-9DD4-4EB2FCB079CC@oracle.com> <540733A8.4060208@univ-mlv.fr> <081A4167-766C-4AAE-ABE8-309F1833E0B8@oracle.com> <540830E3.4060300@univ-mlv.fr> <6B29D8AC-4AF7-413F-8BE1-28F56262DE9D@oracle.com> <54085B35.4030606@univ-mlv.fr> <01A7281F-B8D9-4F2C-9673-3DB8C5801EE9@oracle.com> <541AA3C9.4030302@univ-mlv.fr> Message-ID: <9E8EE502-8A65-49C5-B1CE-3A3FE08276B9@oracle.com> On Sep 18, 2014, at 11:20 AM, Remi Forax wrote: > as i said earlier to John, we don't really need to have one code with multiple shapes, > here what we want is to have type specialization but we will not have it for 9 so > we can use overloads as we usually do to support strawman type specialization. > Still it's somewhat awkward. Some methods like CAS can, as you say, be overloaded but get* methods that take only receiver arguments cannot leaving some methods postfixed with a differentiating string, such as the value type name, and others not. Paul. From forax at univ-mlv.fr Sat Sep 20 08:35:58 2014 From: forax at univ-mlv.fr (Remi Forax) Date: Sat, 20 Sep 2014 10:35:58 +0200 Subject: FTR: JVM Lang Summit presentation In-Reply-To: <9E8EE502-8A65-49C5-B1CE-3A3FE08276B9@oracle.com> References: <4ADC415B-CD55-402A-AC3E-AC8A6C0535BA@oracle.com> <53E0F9DA.3030308@univ-mlv.fr> <1FC8A755-3C36-4B5C-84AE-5A080ADBE926@oracle.com> <53E54267.4030505@univ-mlv.fr> <7884990C-E602-4339-A557-1FDB98FBD3F7@oracle.com> <54060625.3010301@univ-mlv.fr> <884DF874-327D-4409-9DD4-4EB2FCB079CC@oracle.com> <540733A8.4060208@univ-mlv.fr> <081A4167-766C-4AAE-ABE8-309F1833E0B8@oracle.com> <540830E3.4060300@univ-mlv.fr> <6B29D8AC-4AF7-413F-8BE1-28F56262DE9D@oracle.com> <54085B35.4030606@univ-mlv.fr> <01A7281F-B8D9-4F2C-9673-3DB8C5801EE9@oracle.com> <541AA3C9.4030302@univ-mlv.fr> <9E8EE502-8A65-49C5-B1CE-3A3FE08276B9@oracle.com> Message-ID: <541D3C6E.5060604@univ-mlv.fr> On 09/20/2014 12:06 AM, Paul Sandoz wrote: > On Sep 18, 2014, at 11:20 AM, Remi Forax wrote: >> as i said earlier to John, we don't really need to have one code with multiple shapes, >> here what we want is to have type specialization but we will not have it for 9 so >> we can use overloads as we usually do to support strawman type specialization. >> > Still it's somewhat awkward. Some methods like CAS can, as you say, be overloaded but get* methods that take only receiver arguments cannot leaving some methods postfixed with a differentiating string, such as the value type name, and others not. > > Paul. from the API point of view, you can have only one abstract method, let say getOrdered(), and the BSM will wrire to the right implementation, combined with target typing you can have: int i = handle.getOrdered(this); Complex c = handle.getOrdered(this); I'm not sure that target typing is the right solution here, it's perhaps better to use a cast, int i = (int)handle.getOrdered(this); Complex c = (Complex)handle.getOrdered(this); which is i think more readable. Given that the API target people that want to use fine grained concurrency, I don't thing adding a cast is a big deal here. R?mi From jan.lahoda at oracle.com Tue Sep 23 13:09:44 2014 From: jan.lahoda at oracle.com (Jan Lahoda) Date: Tue, 23 Sep 2014 15:09:44 +0200 Subject: Indirect specialized calls Message-ID: <54217118.5060705@oracle.com> Hello, While experimenting with accessors to private specialized fields, I ran across a case where javac produces a classfile that crashes at runtime (on a custom build from valhalla forest). I apologize if this is a known problem, or if I am doing something wrong. The code is like this: --- public class SpecializationTest { public T i; public static TT get(SpecializationTest t) { return t.i; } public static void main(String[] args) { Nested.main(args); } public static class Nested { public static void main(String[] args) { SpecializationTest v = new SpecializationTest<>(); new Nested().call(v); } public TT call(SpecializationTest v) { return get(v); } } } --- The output of javap for the compiled classes is attached. Running the compiled class leads to: --- Specializing SpecializationTest${0=I}; searching for SpecializationTest.class (not found) Specializing SpecializationTest${0=I}; searching for SpecializationTest.class (found) Specializing SpecializationTest$Nested${0=I}; searching for SpecializationTest$Nested.class (not found) Specializing SpecializationTest$Nested${0=I}; searching for SpecializationTest$Nested.class (found) Specializing (LSpecializationTest;)Ljava/lang/Object; to (LSpecializationTest${0=I};)I Exception in thread "main" java.lang.VerifyError: Bad type on operand stack Exception Details: Location: SpecializationTest$Nested${0=I}.call(LSpecializationTest${0=I};)I @1: invokedynamic Reason: Type 'SpecializationTest${0=I}' (current frame, stack[0]) is not assignable to 'SpecializationTest' Current Frame: bci: @1 flags: { } locals: { 'SpecializationTest$Nested${0=I}', 'SpecializationTest${0=I}' } stack: { 'SpecializationTest${0=I}' } Bytecode: 0000000: 2bba 002e 0000 ac at SpecializationTest$Nested.main(SpecializationTest.java:17) at SpecializationTest.main(SpecializationTest.java:10) --- Any idea what is wrong? Thanks, Jan -------------- next part -------------- Classfile /tmp/specialization-test/src/SpecializationTest.class Last modified Sep 23, 2014; size 767 bytes MD5 checksum ccfa8a4d719eb35806b3b0d4083430d6 Compiled from "SpecializationTest.java" public class SpecializationTest extends java.lang.Object minor version: 0 major version: 52 flags: ACC_PUBLIC, ACC_SUPER Constant pool: #1 = Methodref #5.#29 // java/lang/Object."":()V #2 = Fieldref #4.#30 // SpecializationTest.i:Ljava/lang/Object; #3 = Methodref #6.#31 // SpecializationTest$Nested.main:([Ljava/lang/String;)V #4 = Class #32 // SpecializationTest #5 = Class #33 // java/lang/Object #6 = Class #34 // SpecializationTest$Nested #7 = Utf8 Nested #8 = Utf8 InnerClasses #9 = Utf8 i #10 = Utf8 Ljava/lang/Object; #11 = Utf8 Signature #12 = Utf8 TT; #13 = Utf8 #14 = Utf8 ()V #15 = Utf8 Code #16 = Utf8 LineNumberTable #17 = Utf8 get #18 = Utf8 (LSpecializationTest;)Ljava/lang/Object; #19 = Utf8 BytecodeMapping #20 = Utf8 LSpecializationTest;::TTT; #21 = Utf8 TTT; #22 = Utf8 (LSpecializationTest;)TTT; #23 = Utf8 TypeVariablesMap #24 = Utf8 main #25 = Utf8 ([Ljava/lang/String;)V #26 = Utf8 Ljava/lang/Object; #27 = Utf8 SourceFile #28 = Utf8 SpecializationTest.java #29 = NameAndType #13:#14 // "":()V #30 = NameAndType #9:#10 // i:Ljava/lang/Object; #31 = NameAndType #24:#25 // main:([Ljava/lang/String;)V #32 = Utf8 SpecializationTest #33 = Utf8 java/lang/Object #34 = Utf8 SpecializationTest$Nested { public T i; descriptor: Ljava/lang/Object; flags: ACC_PUBLIC Signature: #12 // TT; public SpecializationTest(); descriptor: ()V flags: ACC_PUBLIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: invokespecial #1 // Method java/lang/Object."":()V 4: return LineNumberTable: line 1: 0 line 13: 4 public static TT get(SpecializationTest); descriptor: (LSpecializationTest;)Ljava/lang/Object; flags: ACC_PUBLIC, ACC_STATIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: getfield #2 // Field i:Ljava/lang/Object; 4: areturn LineNumberTable: line 6: 0 BytecodeMapping: Code_idx Signature 1: LSpecializationTest;::TTT; 4: TTT; Signature: #22 // (LSpecializationTest;)TTT; TypeVariablesMap: Tvar_idx Flags 1 [ANY] Ljava/lang/Object; public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: ACC_PUBLIC, ACC_STATIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: invokestatic #3 // Method SpecializationTest$Nested.main:([Ljava/lang/String;)V 4: return LineNumberTable: line 10: 0 line 11: 4 } Signature: #26 // Ljava/lang/Object; SourceFile: "SpecializationTest.java" TypeVariablesMap: Tvar_idx Flags 1 [ANY] Ljava/lang/Object; InnerClasses: public static #7= #6 of #4; //Nested=class SpecializationTest$Nested of class SpecializationTest Classfile /tmp/specialization-test/src/SpecializationTest$Nested.class Last modified Sep 23, 2014; size 1248 bytes MD5 checksum 02d07c1bb9f3fa4b92d9ca4ba4afbd3f Compiled from "SpecializationTest.java" public class SpecializationTest$Nested extends java.lang.Object minor version: 0 major version: 52 flags: ACC_PUBLIC, ACC_SUPER Constant pool: #1 = Methodref #9.#28 // java/lang/Object."":()V #2 = Class #29 // "SpecializationTest${0=I}" #3 = Methodref #2.#28 // "SpecializationTest${0=I}"."":()V #4 = Class #31 // "SpecializationTest$Nested${0=I}" #5 = Methodref #4.#28 // "SpecializationTest$Nested${0=I}"."":()V #6 = Methodref #4.#34 // "SpecializationTest$Nested${0=I}".call:(LSpecializationTest${0=I};)I #7 = InvokeDynamic #0:#39 // #0:get:(LSpecializationTest;)Ljava/lang/Object; #8 = Class #40 // SpecializationTest$Nested #9 = Class #42 // java/lang/Object #10 = Utf8 #11 = Utf8 ()V #12 = Utf8 Code #13 = Utf8 LineNumberTable #14 = Utf8 main #15 = Utf8 ([Ljava/lang/String;)V #16 = Utf8 call #17 = Utf8 (LSpecializationTest;)Ljava/lang/Object; #18 = Utf8 BytecodeMapping #19 = Utf8 LSpecializationTest;::(LSpecializationTest;)TTT; #20 = Utf8 TTT; #21 = Utf8 Signature #22 = Utf8 (LSpecializationTest;)TTT; #23 = Utf8 Ljava/lang/Object; #24 = Utf8 SourceFile #25 = Utf8 SpecializationTest.java #26 = Utf8 TypeVariablesMap #27 = Utf8 Ljava/lang/Object; #28 = NameAndType #10:#11 // "":()V #29 = Utf8 SpecializationTest${0=I} #30 = Class #43 // SpecializationTest #31 = Utf8 SpecializationTest$Nested${0=I} #32 = Utf8 Nested${0=I} #33 = Utf8 InnerClasses #34 = NameAndType #16:#44 // call:(LSpecializationTest${0=I};)I #35 = Utf8 BootstrapMethods #36 = MethodHandle #6:#45 // invokestatic java/lang/invoke/GenericMethodSpecializer.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite; #37 = MethodHandle #6:#46 // invokestatic SpecializationTest.get:(LSpecializationTest;)Ljava/lang/Object; #38 = String #20 // TTT; #39 = NameAndType #47:#17 // get:(LSpecializationTest;)Ljava/lang/Object; #40 = Utf8 SpecializationTest$Nested #41 = Utf8 Nested #42 = Utf8 java/lang/Object #43 = Utf8 SpecializationTest #44 = Utf8 (LSpecializationTest${0=I};)I #45 = Methodref #48.#49 // java/lang/invoke/GenericMethodSpecializer.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite; #46 = Methodref #30.#39 // SpecializationTest.get:(LSpecializationTest;)Ljava/lang/Object; #47 = Utf8 get #48 = Class #50 // java/lang/invoke/GenericMethodSpecializer #49 = NameAndType #51:#54 // metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite; #50 = Utf8 java/lang/invoke/GenericMethodSpecializer #51 = Utf8 metafactory #52 = Class #56 // java/lang/invoke/MethodHandles$Lookup #53 = Utf8 Lookup #54 = Utf8 (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite; #55 = Class #57 // java/lang/invoke/MethodHandles #56 = Utf8 java/lang/invoke/MethodHandles$Lookup #57 = Utf8 java/lang/invoke/MethodHandles { public SpecializationTest$Nested(); descriptor: ()V flags: ACC_PUBLIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: invokespecial #1 // Method java/lang/Object."":()V 4: return LineNumberTable: line 13: 0 public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: ACC_PUBLIC, ACC_STATIC Code: stack=2, locals=2, args_size=1 0: new #2 // class "SpecializationTest${0=I}" 3: dup 4: invokespecial #3 // Method "SpecializationTest${0=I}"."":()V 7: astore_1 8: new #4 // class "SpecializationTest$Nested${0=I}" 11: dup 12: invokespecial #5 // Method "SpecializationTest$Nested${0=I}"."":()V 15: aload_1 16: invokevirtual #6 // Method "SpecializationTest$Nested${0=I}".call:(LSpecializationTest${0=I};)I 19: pop 20: return LineNumberTable: line 15: 0 line 17: 8 line 18: 20 public TT call(SpecializationTest); descriptor: (LSpecializationTest;)Ljava/lang/Object; flags: ACC_PUBLIC Code: stack=1, locals=2, args_size=2 0: aload_1 1: invokedynamic #7, 0 // InvokeDynamic #0:get:(LSpecializationTest;)Ljava/lang/Object; 6: areturn LineNumberTable: line 20: 0 BytecodeMapping: Code_idx Signature 1: LSpecializationTest;::(LSpecializationTest;)TTT; 6: TTT; Signature: #22 // (LSpecializationTest;)TTT; } Signature: #23 // Ljava/lang/Object; SourceFile: "SpecializationTest.java" TypeVariablesMap: Tvar_idx Flags 1 [ANY] Ljava/lang/Object; InnerClasses: public static #32= #4 of #30; //Nested${0=I}=class "SpecializationTest$Nested${0=I}" of class SpecializationTest public static #41= #8 of #30; //Nested=class SpecializationTest$Nested of class SpecializationTest public static final #53= #52 of #55; //Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles BootstrapMethods: 0: #36 invokestatic java/lang/invoke/GenericMethodSpecializer.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite; Method arguments: #37 invokestatic SpecializationTest.get:(LSpecializationTest;)Ljava/lang/Object; #38 TTT; From maurizio.cimadamore at oracle.com Tue Sep 23 13:44:54 2014 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Tue, 23 Sep 2014 14:44:54 +0100 Subject: Indirect specialized calls In-Reply-To: <54217118.5060705@oracle.com> References: <54217118.5060705@oracle.com> Message-ID: <54217956.1030203@oracle.com> In itself, the bytecode looks good. This seems caused by the fact that the specializer is not specializing the static arguments in the bootstrap method. If you run the example with this useful option (thx Brian!): -Dvalhalla.dumpProxyClasses=path_to_specialized_classes The specializer will dump all classes on a given folder. I did that and javap'ed the specialized class SpecializationTest$Nested${0=I} and found the following code for 'call': public int call(SpecializationTest${0=I}); descriptor: (LSpecializationTest${0=I};)I flags: ACC_PUBLIC Code: stack=1, locals=2, args_size=2 0: aload_1 1: invokedynamic #46, 0 // InvokeDynamic #0:get:(LSpecializationTest;)Ljava/lang/Object; 6: ireturn Signature: #29 // (LSpecializationTest${0=I};)I } BootstrapMethods: 0: #38 invokestatic java/lang/invoke/GenericMethodSpecializer.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite; Method arguments: #43 invokestatic SpecializationTest.get:(LSpecializationTest;)Ljava/lang/Object; #45 TTT; As yo can see, the BSM attribute in the specialized class has a bad method handle - it says get(LSpecializationTest) where it should probably say get(LSpecializationTest{0=I}) - hence the error. We are working towards hunting those bugs down. Thanks Maurizio On 23/09/14 14:09, Jan Lahoda wrote: > Hello, > > While experimenting with accessors to private specialized fields, I > ran across a case where javac produces a classfile that crashes at > runtime (on a custom build from valhalla forest). I apologize if this > is a known problem, or if I am doing something wrong. > > The code is like this: > --- > public class SpecializationTest { > > public T i; > > public static TT get(SpecializationTest t) { > return t.i; > } > > public static void main(String[] args) { > Nested.main(args); > } > > public static class Nested { > public static void main(String[] args) { > SpecializationTest v = new SpecializationTest<>(); > > new Nested().call(v); > } > public TT call(SpecializationTest v) { > return get(v); > } > } > } > --- > > The output of javap for the compiled classes is attached. > > Running the compiled class leads to: > --- > Specializing SpecializationTest${0=I}; searching for > SpecializationTest.class (not found) > Specializing SpecializationTest${0=I}; searching for > SpecializationTest.class (found) > Specializing SpecializationTest$Nested${0=I}; searching for > SpecializationTest$Nested.class (not found) > Specializing SpecializationTest$Nested${0=I}; searching for > SpecializationTest$Nested.class (found) > Specializing (LSpecializationTest;)Ljava/lang/Object; to > (LSpecializationTest${0=I};)I > Exception in thread "main" java.lang.VerifyError: Bad type on operand > stack > Exception Details: > Location: > SpecializationTest$Nested${0=I}.call(LSpecializationTest${0=I};)I @1: > invokedynamic > Reason: > Type 'SpecializationTest${0=I}' (current frame, stack[0]) is not > assignable to 'SpecializationTest' > Current Frame: > bci: @1 > flags: { } > locals: { 'SpecializationTest$Nested${0=I}', > 'SpecializationTest${0=I}' } > stack: { 'SpecializationTest${0=I}' } > Bytecode: > 0000000: 2bba 002e 0000 ac > > at SpecializationTest$Nested.main(SpecializationTest.java:17) > at SpecializationTest.main(SpecializationTest.java:10) > --- > > Any idea what is wrong? > > Thanks, > Jan From forax at univ-mlv.fr Tue Sep 23 15:13:08 2014 From: forax at univ-mlv.fr (Remi Forax) Date: Tue, 23 Sep 2014 17:13:08 +0200 Subject: Indirect specialized calls In-Reply-To: <54217956.1030203@oracle.com> References: <54217118.5060705@oracle.com> <54217956.1030203@oracle.com> Message-ID: <54218E04.6040702@univ-mlv.fr> On 09/23/2014 03:44 PM, Maurizio Cimadamore wrote: > In itself, the bytecode looks good. This seems caused by the fact that > the specializer is not specializing the static arguments in the > bootstrap method. If you run the example with this useful option (thx > Brian!): > > -Dvalhalla.dumpProxyClasses=path_to_specialized_classes > > The specializer will dump all classes on a given folder. I did that > and javap'ed the specialized class SpecializationTest$Nested${0=I} and > found the following code for 'call': > > public int call(SpecializationTest${0=I}); > descriptor: (LSpecializationTest${0=I};)I > flags: ACC_PUBLIC > Code: > stack=1, locals=2, args_size=2 > 0: aload_1 > 1: invokedynamic #46, 0 // InvokeDynamic > #0:get:(LSpecializationTest;)Ljava/lang/Object; > 6: ireturn > Signature: #29 // > (LSpecializationTest${0=I};)I > } > BootstrapMethods: > 0: #38 invokestatic > java/lang/invoke/GenericMethodSpecializer.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite; > Method arguments: > #43 invokestatic > SpecializationTest.get:(LSpecializationTest;)Ljava/lang/Object; > #45 TTT; > > As yo can see, the BSM attribute in the specialized class has a bad > method handle - it says get(LSpecializationTest) where it should > probably say get(LSpecializationTest{0=I}) - hence the error. We are > working towards hunting those bugs down. > > Thanks > Maurizio I think you have a similar issue with lambdas. R?mi > > On 23/09/14 14:09, Jan Lahoda wrote: >> Hello, >> >> While experimenting with accessors to private specialized fields, I >> ran across a case where javac produces a classfile that crashes at >> runtime (on a custom build from valhalla forest). I apologize if this >> is a known problem, or if I am doing something wrong. >> >> The code is like this: >> --- >> public class SpecializationTest { >> >> public T i; >> >> public static TT get(SpecializationTest t) { >> return t.i; >> } >> >> public static void main(String[] args) { >> Nested.main(args); >> } >> >> public static class Nested { >> public static void main(String[] args) { >> SpecializationTest v = new SpecializationTest<>(); >> >> new Nested().call(v); >> } >> public TT call(SpecializationTest v) { >> return get(v); >> } >> } >> } >> --- >> >> The output of javap for the compiled classes is attached. >> >> Running the compiled class leads to: >> --- >> Specializing SpecializationTest${0=I}; searching for >> SpecializationTest.class (not found) >> Specializing SpecializationTest${0=I}; searching for >> SpecializationTest.class (found) >> Specializing SpecializationTest$Nested${0=I}; searching for >> SpecializationTest$Nested.class (not found) >> Specializing SpecializationTest$Nested${0=I}; searching for >> SpecializationTest$Nested.class (found) >> Specializing (LSpecializationTest;)Ljava/lang/Object; to >> (LSpecializationTest${0=I};)I >> Exception in thread "main" java.lang.VerifyError: Bad type on operand >> stack >> Exception Details: >> Location: >> SpecializationTest$Nested${0=I}.call(LSpecializationTest${0=I};)I @1: >> invokedynamic >> Reason: >> Type 'SpecializationTest${0=I}' (current frame, stack[0]) is not >> assignable to 'SpecializationTest' >> Current Frame: >> bci: @1 >> flags: { } >> locals: { 'SpecializationTest$Nested${0=I}', >> 'SpecializationTest${0=I}' } >> stack: { 'SpecializationTest${0=I}' } >> Bytecode: >> 0000000: 2bba 002e 0000 ac >> >> at SpecializationTest$Nested.main(SpecializationTest.java:17) >> at SpecializationTest.main(SpecializationTest.java:10) >> --- >> >> Any idea what is wrong? >> >> Thanks, >> Jan > From brian.goetz at oracle.com Tue Sep 23 17:49:12 2014 From: brian.goetz at oracle.com (Brian Goetz) Date: Tue, 23 Sep 2014 13:49:12 -0400 Subject: Indirect specialized calls In-Reply-To: <54217118.5060705@oracle.com> References: <54217118.5060705@oracle.com> Message-ID: <5421B298.50205@oracle.com> So, I've got an incomplete patch in progress that helps slightly, it rewrites the invocation signature for the indy call but not yet the static arguments. I hope to clean this up and get it put back soon. We're still a bit away for i) instance generic methods, ii) specialization of inner classes, iii) specialization of local classes. But we should soon get to where static generic methods can be cleanly specialized. I recently pushed support for specialization to long/double, which had been victim of the classic "two stack slots" problem. Remi made a point about lambdas -- can you elucidate what will go wrong here? On 9/23/2014 9:09 AM, Jan Lahoda wrote: > Hello, > > While experimenting with accessors to private specialized fields, I ran > across a case where javac produces a classfile that crashes at runtime > (on a custom build from valhalla forest). I apologize if this is a known > problem, or if I am doing something wrong. > > The code is like this: > --- > public class SpecializationTest { > > public T i; > > public static TT get(SpecializationTest t) { > return t.i; > } > > public static void main(String[] args) { > Nested.main(args); > } > > public static class Nested { > public static void main(String[] args) { > SpecializationTest v = new SpecializationTest<>(); > > new Nested().call(v); > } > public TT call(SpecializationTest v) { > return get(v); > } > } > } > --- > > The output of javap for the compiled classes is attached. > > Running the compiled class leads to: > --- > Specializing SpecializationTest${0=I}; searching for > SpecializationTest.class (not found) > Specializing SpecializationTest${0=I}; searching for > SpecializationTest.class (found) > Specializing SpecializationTest$Nested${0=I}; searching for > SpecializationTest$Nested.class (not found) > Specializing SpecializationTest$Nested${0=I}; searching for > SpecializationTest$Nested.class (found) > Specializing (LSpecializationTest;)Ljava/lang/Object; to > (LSpecializationTest${0=I};)I > Exception in thread "main" java.lang.VerifyError: Bad type on operand stack > Exception Details: > Location: > SpecializationTest$Nested${0=I}.call(LSpecializationTest${0=I};)I > @1: invokedynamic > Reason: > Type 'SpecializationTest${0=I}' (current frame, stack[0]) is not > assignable to 'SpecializationTest' > Current Frame: > bci: @1 > flags: { } > locals: { 'SpecializationTest$Nested${0=I}', > 'SpecializationTest${0=I}' } > stack: { 'SpecializationTest${0=I}' } > Bytecode: > 0000000: 2bba 002e 0000 ac > > at SpecializationTest$Nested.main(SpecializationTest.java:17) > at SpecializationTest.main(SpecializationTest.java:10) > --- > > Any idea what is wrong? > > Thanks, > Jan From jan.lahoda at oracle.com Wed Sep 24 20:52:07 2014 From: jan.lahoda at oracle.com (Jan Lahoda) Date: Wed, 24 Sep 2014 22:52:07 +0200 Subject: Indirect specialized calls In-Reply-To: <5421B298.50205@oracle.com> References: <54217118.5060705@oracle.com> <5421B298.50205@oracle.com> Message-ID: <54232EF7.4070504@oracle.com> Maurizio, Brian, Thanks a lot for your comments and explanations. Jan On 23.9.2014 19:49, Brian Goetz wrote: > So, I've got an incomplete patch in progress that helps slightly, it > rewrites the invocation signature for the indy call but not yet the > static arguments. I hope to clean this up and get it put back soon. > > We're still a bit away for i) instance generic methods, ii) > specialization of inner classes, iii) specialization of local classes. > But we should soon get to where static generic methods can be cleanly > specialized. > > I recently pushed support for specialization to long/double, which had > been victim of the classic "two stack slots" problem. > > Remi made a point about lambdas -- can you elucidate what will go wrong > here? > > On 9/23/2014 9:09 AM, Jan Lahoda wrote: >> Hello, >> >> While experimenting with accessors to private specialized fields, I ran >> across a case where javac produces a classfile that crashes at runtime >> (on a custom build from valhalla forest). I apologize if this is a known >> problem, or if I am doing something wrong. >> >> The code is like this: >> --- >> public class SpecializationTest { >> >> public T i; >> >> public static TT get(SpecializationTest t) { >> return t.i; >> } >> >> public static void main(String[] args) { >> Nested.main(args); >> } >> >> public static class Nested { >> public static void main(String[] args) { >> SpecializationTest v = new SpecializationTest<>(); >> >> new Nested().call(v); >> } >> public TT call(SpecializationTest v) { >> return get(v); >> } >> } >> } >> --- >> >> The output of javap for the compiled classes is attached. >> >> Running the compiled class leads to: >> --- >> Specializing SpecializationTest${0=I}; searching for >> SpecializationTest.class (not found) >> Specializing SpecializationTest${0=I}; searching for >> SpecializationTest.class (found) >> Specializing SpecializationTest$Nested${0=I}; searching for >> SpecializationTest$Nested.class (not found) >> Specializing SpecializationTest$Nested${0=I}; searching for >> SpecializationTest$Nested.class (found) >> Specializing (LSpecializationTest;)Ljava/lang/Object; to >> (LSpecializationTest${0=I};)I >> Exception in thread "main" java.lang.VerifyError: Bad type on operand >> stack >> Exception Details: >> Location: >> SpecializationTest$Nested${0=I}.call(LSpecializationTest${0=I};)I >> @1: invokedynamic >> Reason: >> Type 'SpecializationTest${0=I}' (current frame, stack[0]) is not >> assignable to 'SpecializationTest' >> Current Frame: >> bci: @1 >> flags: { } >> locals: { 'SpecializationTest$Nested${0=I}', >> 'SpecializationTest${0=I}' } >> stack: { 'SpecializationTest${0=I}' } >> Bytecode: >> 0000000: 2bba 002e 0000 ac >> >> at SpecializationTest$Nested.main(SpecializationTest.java:17) >> at SpecializationTest.main(SpecializationTest.java:10) >> --- >> >> Any idea what is wrong? >> >> Thanks, >> Jan From simon at ochsenreither.de Tue Sep 30 15:10:22 2014 From: simon at ochsenreither.de (Simon Ochsenreither) Date: Tue, 30 Sep 2014 17:10:22 +0200 Subject: Notes about Valhalla from a non-Java perspective Message-ID: <542AC7DE.7040905@ochsenreither.de> Hi, it seems that no one from the Scala team found enough time/interest to participate on valhalla-dev (Martin mentioned that most of the Scala team is on holidays/in a move/in recovery) yet ... I would have preferred to not get involved (bad impressions from other OpenJDK lists), but I'll just post my personal notes (which I sent to scala-internals a few weeks earlier) here directly before they fall completely out of date. Please note that it's written from a Scala development perspective, so "we" == "arbitrary group of Scala devs/users". Here are my (slightly improved) notes: ============== * On the general approach of using class file attributes with tuples of (bytecode index -> type) It's kind of funny, because that's exactly the approach I took almost 18 months earlier when I was thinking about this topic. I considered that to be quite a hack at that time and thought "if the JVM ever gets this, they will surely come up with a more principled way of doing this". * vcmp This feels a bit ad-hoc currently. I think it would be considerably more useful if they tried to come up with a design which would work across all types, and not yet-another special case. Scala's == implementation for instance is around 100 lines of code with dozens of branches to work around Java's/the JVM's idea of equality. It would be nice that if they were adding another comparison operator that they wouldn't repeat the mistakes of equals & friends. They could be on the right way, but hard to tell without looking at it more closely. My suggestion would be to have a notion of "primitive" equality which is defined as "do the most basic comparison available": Compare the bits of the underlying value, which means ... o the bits of value types, taking types into account o the bits of the reference for reference types o wrappers are unboxed o Double.NaN is equal to itself, 0.0 and -0.0 are not equal This would be pretty much be in line with our earlier debate about supporting eq on value types. If this could be encoded as a single vcmp operation, it would be a huge win. Additionally, one could also consider a corresponding operation for "semantic" equality: o Use "equals" implementation for value types o Use Java-style "==" for primitives o Wrappers are unboxed o Use "equals" implementation for references o Double.NaN is not equal to itself, 0.0 and -0.0 are equal o (Optionally) Compare arrays by comparing the element That would vastly simplify our == implementation, but that's not really the point ... it would be possible to do that, but I think priority should be to prevent vcmp from being either artificially limited to value types or ending up incoherent like the rest of equality stuff in Java. In the end, I think how to deal with primitive wrappers is still an uncharted territory. Retrofitting those wrapper classes as value boxes very likely won't work, so maybe there is more specification required on how "T=Integer" for "any T" is treated (or int in need of a box in specialized code). * No reification for reference types (Reified in the sense of "the type is available at runtime", not "it gets a specialized class".) I'm split on this. On the one side, this could give us the escape hatch for types not expressible with the new Generics, but on the other hand it would really suck because it would mean we couldn't just drop ClassTags altogether, but would need to drag them around for every type even if only references would actually need them. Additionally, the split between value types/reference types is very likely not similar to the split we would need to erase Scala's types to the JVM's level of expressiveness. It feels like they are again trying to cut corners here, trading implementation ease for additional language complexity. (As far as I remember, there were some concerns about what happens with Java's .class/getClass() when reference types are reified ... but imho, Java problems should stay Java problems and shouldn't make the JVM approach worse than necessary.) Also note, how this fits with my work on making classOf[T] ClassTag-aware. Additionally, we have already an escape hatch with the existing erased Generics, so having yet-another different style of Generics doesn't feel like the right way ... which brings us to the next point: * Reified/Erased Generics interop This seems to be a really dark corner. The draft is pretty silent on this. It currently looks like you can't have a type hierarchy were A is erased at the top but reified in a a subclass (or the other way around) ... I think this will make it very hard to use erased Generics as an escape hatch. Combined with the earlier point, I'd prefer better reified/erased interop and having reified reference types with reified Generics. Otherwise, it feels like tons of people will try to wrap random reference types in value types to get around that limitation. * No variance for value types This is a big conceptual problem with heterogeneous translation and my personal conclusion 1.5 years ago was the same: It can't really be done without a huge explosion in runtime complexity. * Poor man's typeclasses There was a short mention of "conditional methods", e.g. enabling methods only for a subset of some generic type. That smells a lot like a crippled version of typeclasses. Might be useful to watch what happens in that space. * Members on any T There seems to be a debate about whether/how "any T" should expose methods by itself. While this seems to be nicely in line with what a lot of people in Scala would like to do, I think Java will not be able to properly add constraints to T to describe required methods. They currently only have upper bounds to express those things, but even in Scala where bounds are less horrible than in Java, people have pretty much abandoned bounds based on subtyping in favor of context bounds. So even if Any/T wouldn't get any members I think we should be aware that Java's options for adding constraints are very, very primitive and probably not what we would want to use in Scala. Let's take that into account before arguing for or against this ... My conclusion regarding Scala: * Exposing two kinds of Generics to the user is highly undesirable from a language design POV. F# did the same with a much better starting point than Java (well-designed runtime support for reified Generics) and even for them I think the increase of complexity just wasn't worth the benefit. Java might not have a choice here, but I think we should make sure to not leak these "implementation details" to the user. We will have to support both kinds of Generics for interop anyway. * We should think about how we would like to see T/Any and eq/== evolve in the long-term and communicate that clearly to the Valhalla people. It's probably much more painful if they e.g. decide to have no members on any T, but decide on an incompatible constraint mechanism (which would very likely be reified in the bytecode). That way, keeping status quo and implementing member-free Any/T as a scalac fiction might work better. * We should start preparing for the variance/value type breakage. People who need variance can migrate to boxed representations easily (replace Vector[Int] with Vector[Integer] for instance), but trying to keep things as-is would mean just not supporting JVM value types, and I think that would be a terrible decision. From a type system POV, instantiating a type parameter with a value type could be seen as collapsing all the bounds of that type parameter to make it invariant * We should really think about having a scalac prototype which tries to emit the new class file format and leverage the new semantics. There is already an ASM fork out there with preliminary support, but I don't know how stable/complete that code is. Experience has shown (JRuby) that this is the most effective way to actually influence the design. That's just some short overview, I can expand on these topics as necessary, but I expect that people have read the draft proposal and the complete mailing list already so that everyone is on roughly the same level. ============== I hope this is helpful. Thanks, Simon