JDK-8153870 : Result-boxed and result-less VarHandles are significantly penalized
  • Type: Sub-task
  • Component: core-libs
  • Sub-Component: java.lang.invoke
  • Affected Version: 9
  • Priority: P2
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2016-04-08
  • Updated: 2016-07-05
  • Resolved: 2016-05-07
Related Reports
Blocks :  
Relates :  
Relates :  
Description
This might be generic to VarHandles to begin with, but best demonstrated with this CompareAndExchangeTest:
 http://cr.openjdk.java.net/~shade/8153870/BadCAE.java
 http://cr.openjdk.java.net/~shade/8153870/bad-cae.txt

The problem is that we hit slow-path if we don't match the signature exactly.
Comments
I agree (regardless of the specifics of invocation behaviour). What about the following cases? (Assume 1) and 2) are the invokevirtual invocation and findVirtual MH invokeExact invocation respectively) 2) MethodHandle mh = vh.toMethodHandle(VarHandle.AccessMode.{access-mode}); // Note the vh instance is bound to the returned MH R r = (R) invokeExact(p1, p2, ..., pN); 3) MethodHandle mh = MethodHandles.varHandleExactInvoker( VarHandle.AccessMode.{access-mode}, MethodType.methodType(R, P1, P2, ..., PN)); R r = (R) mh.invokeExact(vh, p1, p2, ..., pN); 4) MethodHandle mh = MethodHandles.varHandleInvoker( VarHandle.AccessMode.{access-mode}, MethodType.methodType(R, P1, P2, ..., PN)); R r = (R) mh.invokeExact(vh, p1, p2, ..., pN);
12-04-2016

yes, with the small difference that invokExact requires you to catch/throws Throwable.
12-04-2016

Should the behaviour of: VarHandle vh = .. R r = (R) vh.{access-mode}(p1, p2, ..., pN); be equivalent to: MethodHandle mh = MethodHandles.lookup().findVirtual( VarHandle.class, VarHandle.AccessMode.{access-mode}.name(), MethodType.methodType(R, P1, P2, ..., PN)); R r = (R) mh.invokeExact(vh, p1, p2, ..., pN) ? The key to expressing invokevirtual behaviour of VH access mode methods is as if by transformation to a MH and invoking it.
12-04-2016

I believe there is a way to see a VarHandle as a method handle in the API, so the invoke generic semantics can be supported that way. So a call using a VH directly can be restricted to your case 1.1 and 1.2.
12-04-2016

Most use-cases are expected to be supported by exact or erased sigs, but still the user has to be careful of the edge cases when LambdaForms may kick in. The dropping of the return type is the most non-obvious one to me. If one has boxing/conversion going on then all performance bets are off IMO. But the user has no control, an edge case could slip in by mistake, which i think is your main point. What do you think of supporting both exact and generic invocation? by default a VH supports exact invocation and can be transformed to support generic invocation? That might muddy the picture with regards to findVirtual and invokers to VH access mode methods.
12-04-2016

How a user can know that a specific call is a use case ? That's exactly the reason why there is an invokeExact and an invoke, at least the perf characteristics is clear for anyone.
12-04-2016

It's only "slow" because i have yet to optimize it, some quick hacking indicates i can reduce the cost significantly. I want to support the equivalent MH.invoke semantics, with, or equivalent of, an asType transformation when 1.1/1.2 do not match. We could consider throwing an exception for 1.3. We would still require 2 (which in effect is the same as 1 but using lambda forms) unless we pre-generate all required signatures (which we can do) to capture all linkage routes. That may make the VH invocation semantics a little murkier, but could be specified as the equivalent of obtaining a MH to the access mode method and then, i am guessing, applying a guardWithCheck. The downside is then the subtle difference between MH invocation and VH invocation. Another solution is for a VH to support two invocation kinds. The first is exact/erased and it can be transformed to support the full asType case e.g. VarHandle vh = ... vh_i = vh.generic(); Which arguably increases the murkiness. The expectation is these paths will be edge cases given VHs will likely be wrapped and/or used with exact/erased signatures.
12-04-2016

Why do you want to support slow call ? It will be a surprise for everyone that use the VarHandle API instead of the reflection API. In my opinion, in case 1.3 and 2, the code should throw an exception. ARFU semantics already has this issue and this is one reason people starts using sun.misc.Unsafe.
12-04-2016

Invocation of VH sig-poly methods currently supports two general linkage mechanisms: 1) Direct linkage when the callee signature matches a known signature of a method in VarHandleGuards. This avoids LambdaForms and class spinning. The set of known signatures is based on the support variables and types. 2) LambdaForm linkage (similar to how MH.invoke works), when there is no signature match for 1) (Note: 1) can be disabled with -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false) Direct linkage supports three invocation paths: 1.1) exact callee and target signature matching 1.2) exact erased callee and target signature matching (with ref cast checks in the implementation) 1.3) a slow path that creates a method handle from MethodHandles.varHandleInvoker and invokes it with invokeBasic (since there is no need to check the arguments against the callee signature) At the moment there has not been much attempt to optimize 2) and 1.3). For example, there is no caching of handles.
08-04-2016