Strict long type casting
Ty Young
youngty1997 at gmail.com
Tue Apr 7 19:38:07 UTC 2020
On 4/7/20 4:59 AM, Maurizio Cimadamore wrote:
>
>
> On 07/04/2020 02:54, Ty Young wrote:
>>
<snip>
> This seems expected; intValue() does this:
>
> return (int)this.handle.get(this.address);
>
> You have a var handle whose carrier type is a long; but the client is
> enforcing a cast to int - meaning that the method type used to do the
> get will be something like
>
> (MemoryAddress) -> int
>
> The set of allowed conversions are described here:
>
> https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/lang/invoke/MethodHandle.html#asType(java.lang.invoke.MethodType)
>
> More specifically, primitive "widening" conversions are allowed. Going
> from a "long" to an "int" is not a widening. For more information
> about widening conversions, see here:
>
> https://docs.oracle.com/javase/specs/jls/se14/html/jls-5.html#jls-5.1.2
>
> I suspect that if you setup a matrix test where you call all the
> XYZvalue() methods on _all_ the NativeXYZ instances you will see more
> failures like that. E.g. I would expect NativeDouble to suffer from
> same issues.
>
>
> Now, back to your problem, I don't think there's a way to express all
> the XYZvalue() methods generically as you are trying to do in the
> abstract class. Well, there are ways, but they are very roundabout -
> for instance you could:
>
> * turn the VarHandle into a MethodHandle and then use
> MethodHandles.explicitCastArguments - which does a true cast:
>
> https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/lang/invoke/MethodHandles.html#explicitCastArguments(java.lang.invoke.MethodHandle,java.lang.invoke.MethodType)
>
> * Or you could adapt the VarHandle using the MethodHandles.filterValue
> combinator we have added, to turn the long VH into a truncating int VH
>
>
> But, I believe, the best way to address this is to replicate the
> XYZvalue() code in the various subclasses, so that you insert all the
> correct cast - for instance you can do this:
>
>
> class NativeLong<...> {
> ...
> int intValue() {
> return (int)(long)this.handle.get(this.address);
> }
> }
>
> This should address the issue, and you should also be able to make the
> code "more static" since, I suspect, the VarHandle to be used in a
> NativeLong is always the same and can be cached statically - this
> gives you quite a bit of a boost when using it to access off heap
> memory as the JIT compiler is then able to inline the VarHandle code
> in the caller.
>
Yep, that works. I guess Integer just happens to work because the value
is type casted to int first then byte so effectively it is the same as:
(byte)(int)this.handle.get(this.address);
Anyway, thanks.
Question: can the JIT compiler still perform these optimizations if the
VarHandle(s) are stored in a Map so long as the references are final?
Currently(as shown in the code), I'm doing just that to cut down on the
amount of wasted memory on the exact same VarHandle(s) as I'd otherwise
have 60+ instances.
> Maurizio
>
More information about the panama-dev
mailing list