FTR: JVM Lang Summit presentation
forax at univ-mlv.fr
Thu Sep 4 12:29:41 UTC 2014
On 09/04/2014 01:26 PM, Paul Sandoz wrote:
> On Sep 4, 2014, at 11:29 AM, Remi Forax <forax at univ-mlv.fr> 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
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.
More information about the valhalla-dev