[foreign-abi] RFR: 8254260: Consider splitting binding recipe operators that serve a dual role
Jorn Vernee
jvernee at openjdk.java.net
Fri Oct 9 12:13:46 UTC 2020
On Thu, 8 Oct 2020 20:25:31 GMT, Maurizio Cimadamore <mcimadamore at openjdk.org> wrote:
>> Hi,
>>
>> This patch splits the binding recipe operators that currently serve a dual purpose into 2 operators each:
>> - MOVE -> VM_STORE and VM_LOAD
>> - DEREFERENCE -> BUFFER_STORE and BUFFER_LOAD
>> - CONVERT_ADDRESS -> BOX_ADDRESS and UNBOX_ADDRESS
>>
>> Note that I also added a TO_SEGMENT operator which converts a MemoryAddress into a MemorySegment. This was previously
>> done as part of the COPY operator, but only for upcalls, so I had to split out this functionality so that COPY could
>> have only one interpretation as well. This will also enable some more optimizations down the line, such as merely
>> wrapping a by-value struct passed as a pointer in a MemorySegment, instead of having to make a copy. This also
>> regularized the use of allocators by the operators. Now an allocator is always passed as an argument, and that's what
>> is used to do allocations, instead of relying implicitly on MemorySegment::allocateNative. (The index of the allocator
>> argument is now also always passed when specializing an operator, to indicate the dependency, and so that operator
>> impls don't have to 'guess' which argument index is the allocator (see for instance the implementation of
>> Copy::specialize). The rest of the patch is more or less a mechanical renaming, and updating the tests/CallArrangers
>> to use the different operator names. Thanks, Jorn
>
> src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/ProgrammableInvoker.java line 344:
>
>> 342: Map<VMStorage, Integer> retIndexMap) throws Throwable {
>> 343: boolean hasBufferCopies = bufferCopySize != 0;
>> 344: NativeScope scope = hasBufferCopies ? NativeScope.boundedScope(bufferCopySize) : null;
>
> If Allocator had a close() method, this could be simplified a little?
This is not really a problem with Allocator, it's a problem with having either a NativeScope, or having none (null),
which will result in an NPE when trying to reference `scope::allocateNative`. That's why this code is conditional.
> src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/ProgrammableInvoker.java line 219:
>
>> 217: MethodHandle specializedHandle = leafHandle; // initial
>> 218:
>> 219: int argInsertPos = -1;
>
> The more we tweak this routine, the more I'm convinced we should just spin specialized bytecode :-) - it's becoming
> increasingly hard to follow what's happening here. (not for this review - more longer term)
Yeah, especially the indexing is tricky since we have to walk the recipe in reverse, but we shouldn't have that problem
when spinning bytecode.
> src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/Binding.java line 230:
>
>> 228:
>> 229: enum Tag {
>> 230: VM_STORE,
>
> Should these be called REG_STORE and REG_LOAD? Ah, I guess we also have stack, right? Ok, I agree with the name - these
> are "moves" that only the VM can perform, makes sense.
REG_LOAD and REG_STORE also works for me. The name is derived from VMReg in the HotSpot code -> VMStorage in our
code -> VM_LOAD/VM_STORE. (So, REG works equally well).
> src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/Binding.java line 591:
>
>> 589: * The [type] must be one of byte, short, char, int, long, float, or double
>> 590: */
>> 591: public static class BuffferStore extends Dereference {
>
> Typo, there are 3 `f`
Thanks!
> src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/CallingSequenceBuilder.java line 93:
>
>> 91:
>> 92: for (Binding b : bindings) {
>> 93: if (b.tag() == Binding.Tag.VM_LOAD
>
> We could have static EnumSet for what's an box vs. unbox binding, so that you can filter by checking for presence in
> the right enum set?
Yeah, that's a good idea.
> src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/ProgrammableUpcallHandler.java line 102:
>
>> 100: : bufferBase.asSlice(layout.argOffset(storage));
>> 101: return SharedUtils.read(ptr, type);
>> 102: }, DEFAULT_ALLOCATOR);
>
> For upcalls, couldn't we use a `NativeScope` and close at the end of the call? If the callback leaks segments
> outside... well, too bad.
Yes, exactly. But, seemed like a separate patch.
-------------
PR: https://git.openjdk.java.net/panama-foreign/pull/375
More information about the panama-dev
mailing list