BUG: SystemABI C_LONG and C_LONGLONG are the same

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Wed May 20 13:41:09 UTC 2020

On 19/05/2020 15:05, Ty Young wrote:
> I don't think hiding low level Panama details is the way to go about 
> things, and I hope that if Panama does add a higher level API, it 
> doesn't go the route of trying to directly model C code like "Pointer" 
> kinda sorta did.
> I'd personally like to see something like I did, but I'm both biased 
> and realize it's probably unrealistic. The amount of classes that this 
> otherwise thin abstraction layer is a bit much for the JDK. In my 
> defense, the type specific values and arrays only exist because Java 
> doesn't support primitive generics.
> It would be interesting to get a wider perspective on which approach 
> is better. Do people think a smaller higher-level API is better which 
> has more "god-like" objects or is a more thinly spread, targeted, and 
> lots of classes better? I largely stand by the way I went about it, 
> but I'm still personally interested in what others prefer and think. 

This is a very good and constructive point. What kind of high-level API 
would people expect?

By having spent time looking at what other languages did in this area 
(e.g. Kotlin, Swift and the likes), and, by also looking at what more 
traditional Java bindings for native libraries do (e.g. LWJGL) - at some 
point they all seem to reach out for some kind of pointer-like 
abstraction. So I think that _not_ having some kind of higher-level 
Pointer abstraction in the long run could be counter-productive.

The problem you raise about lack of support for primitives (and, more 
generally, looking forward to Valhalla) inline classes inside generics 
(although we have plans for those) remains, IMHO, one of the main 
blockers to provide one such abstraction. My personal opinion is that 
the old pointer API was not too bad, but it failed because it doesn't go 
the full way towards supporting the full spectrum of C types.

That is, at some point, libraries are going to start modelling a "C 
int", or a "C unsigned long" as a Java int/long - for primarily three 

* avoid any cost associated with GC
* take advantage of the fact that Java primitives have 'literals' (e.g. 42L)
* operators are available on primitives - they become methods on classes 
(e.g. 2 + 3 vs two.plus(three))

There's of course a _lot_ of overlapping with Valhalla here. My sense is 
that Valhalla will allows us to reach that carrier type Nirvana that 
Panama so badly needs - you need C unsigned ints? Why not just defining 
a new inline class `c_unsigned_int` so that you can then operate on it, 
create pointers (e.g. `Pointer<c_unsigned_int>`) and so on and so forth?

If we pull that off, then your Java code will look a lot like the C code 
that it came from - you will no longer be using `int` as an 
approximation for a richer C carrier (which was the trick the old API 
was doing) - you will use the carrier you want, with (almost) the name 
you want. IMHO this is much better than just using `int` and maybe 
sprinkle a bunch of annotation on the side to say "this int is really XYZ".

As a side-effect, bindings written this way will also be more portable 
too - since abstractions such as `c_unsigned_long` and the likes can be 
coded in a way so that they take into account platform differences. 
Which means the signatures of your methods do not change across platforms.

But an approach such as the one I'm musing here requires a lot of help 
from Valhalla to make it real. I did some experiments with some 
high-level pointer API built on top of FMA, and while the performance 
numbers in some cases are really really good (when C2 can see escape 
analysis all the way down), in certain cases they can be 10x off what 
the low level FMA is at. And performance is not the only issue - I would 
suspect that w/o some form of operator overloading, programming with 
`c_unsigned_int` would be considerably fussier than with a plain Java 
int, so we also need some of the expressiveness enhancements that will, 
at some point, be considered as part of Valhalla.

But, these experiments also were useful in proving another point: that, 
at the time of writing, the low level FMA is, by far, the fastest option 
available for foreign memory access (albeit low level). Adding 
abstractions on top is possible, but they all come with some kind of 
hefty price tag attached - so I suspect that developers (especially 
framework developers) might want to think twice before adding too much 
abstractions on top of the basic memory access.

Hopefully, the evolution of the Java platform will allow us to have our 
cake and eat it too - e.g. have plenty of inline (GC-free) carriers 
which developer can operate upon as if they were primitives - at which 
point we'd no longer have to choose between expressiveness and performances.


More information about the panama-dev mailing list