Binding a single function symbol with [foreign]
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
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).
<snip>
> 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
and
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
#endif
};
static Register integer_return_registers[INTEGER_RETURN_REGISTERS_NOOF] = {
rax,
#ifndef _WIN64
rdx
#endif
};
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
#endif
};
static XMMRegister vector_return_registers[VECTOR_RETURN_REGISTERS_NOOF] = {
xmm0,
#ifndef _WIN64
xmm1
#endif
};
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...
Thanks
Maurizio
More information about the panama-dev
mailing list