Binding a single function symbol with [foreign]

Maurizio Cimadamore maurizio.cimadamore at
Mon Sep 10 13:38:49 UTC 2018

On 10/09/18 13:24, Jorn Vernee wrote:
> Yeah, I suppose there is not much difference if I'm using a pointer to 
> a library symbol. My views on this have changed, I assumed wrapping a 
> single function in a MethodHandle would be easier. But, you still need 
> the same information, using an interface is just a different way of 
> providing it. Though my idea might still be a good solution for when 
> you have an arbitrary void Pointer that you want to make invokable, or 
> when you want to 'cast' a Callback to a different type (i.e. 
> Callback.entryPoint() -> void Pointer -> 
> Pointer.asCallback(SomeOtherCallbackType.class)) ?
Sure - the allocateCallback is, as you note, a way to convert function 
pointers into functional interfaces callable from Java, so that's 
correct. It's just that, in your case, since the symbol is publicly 
available in the library, you are doing by hand, what Libraries::bind 
already does for free ;-)

But yes, if the native code were to allocate some code stub and you 
wanted to call it from Java, in that case you'd have to use the Callback 
mechanism (as that would NOT be a library symbol).

> Yeah - windows is not supported - I'm actually surprised it works at
>> all, given that the registers used by the Windows ABI and system V ABI
>> are quite different; for instance, System V (the implemented one)
>> passes its first integer argument via the RDI register, whereas the
>> Windows ABI uses RCX; so the failure you are seeing is related to the
>> fact that the current code doesn't arrange the arguments/return values
>> in a way that is compatible with the underlying system ABI on your
>> machine.
> Using -Xlog:panama I did see the first argument being put into RCX. 
> Maybe that's just a coincidence? tbh I didn't know different ABIs were 
> being used. For the standard library I always thought 32bit used 
> cdecl, and 64bit used fastcall, which I thought would use the same 
> registers on all systems. That's interesting to hear (I don't dabble 
> in ABIs too often).
Ah - now that I think about it, the hotspot code abstracts over details 
such as these - as internally it uses register names such as

c_rarg0 .... c_rarg_N,  for integer registers


c_farg0 ... c_farm_M, for FP registers

In fact, looking more in details at nativeInvoker_x86.cpp, it looks like 
the right thing happens:

static Register 
integer_argument_registers[INTEGER_ARGUMENT_REGISTERS_NOOF] = {
   c_rarg0, c_rarg1, c_rarg2, c_rarg3,
#ifndef _WIN64
   c_rarg4, c_rarg5

static Register integer_return_registers[INTEGER_RETURN_REGISTERS_NOOF] = {
#ifndef _WIN64

static XMMRegister 
vector_argument_registers[VECTOR_ARGUMENT_REGISTERS_NOOF] = {
   c_farg0, c_farg1, c_farg2, c_farg3,
#ifndef _WIN64
   c_farg4, c_farg5, c_farg6, c_farg7

static XMMRegister vector_return_registers[VECTOR_RETURN_REGISTERS_NOOF] = {
#ifndef _WIN64

So, for simple calls like puts, which take a single integer register 
value and returns via a single register value, things *should* work - 
but it seems like it doesn't. Anyway, the current support is, as I 
wrote, mostly Linux and MacOs centric - and we're not planning to do 
Windows tweak in the short term at least. But your experiment suggests 
that we might not be that far off the mark...


More information about the panama-dev mailing list