New candidate JEP: 370: Foreign-Memory Access API
Vladimir Ivanov
vladimir.x.ivanov at oracle.com
Thu Nov 28 17:24:42 UTC 2019
>> Second, what about an API to allocate memory from the stack? This is
>> really useful in GraalVM (granted they have a sort-of-Panama-ish way
>> of calling C functions already, and they're really quite "loose" when
>> it comes to safety in some regards) and could simplify some things
>> already, particularly if the pointer could then be passed to a JNI
>> method. Given the sensitive nature of stack allocation you'd probably
>> have to add some extra checks (like checking that the thread matches
>> on each access and that it is in scope, and you'd probably have to do
>> the latter via callback like StackWalker does) but it would be pretty
>> useful nonetheless.
>
> I guess it depends on what the goal is here - if the goal is to 'speed
> up allocation', there are other ways to skin that cat (and we're
> actually working on what seems like a very promising direction which we
> should be able to communicate more publicly soon). But, another related
> goal would be to be able to express stack allocation in Java directly,
> so that some of the work for e.g. writing bridge code which goes from
> Java to native can be expressed in Java directly. While something like
> this would probably be useful, as an implementation tool (e.g. to
> implement our own programmable invoker [2]), I don't see that being a
> priority from a public API perspective (assuming we can make allocation
> fast enough - that is!).
Yes, stack allocation looks attractive, but in practice its usability is
quite limited. (IMO thread-local arena-style memory allocator is more
practical.) And it makes some assumptions about how threads and stacks
work which are aren't specified by JVMS, but are implementation details.
For example, how will it interact with Project Loom?
Leaving high-level considerations aside, there's already a way to build
stack allocator without any JVM assistance on top of JNI (though
definitely not the most efficient and performant one):
- do a native call;
- allocate memory on stack inside native frame;
- do an upcall to user-provided callback and pass a pointer to
allocated memory;
On Java level it can be exposed as:
<R> native R allocateOnStack(long size, LongFunction<R> task);
What Memory Access API can add to it is safety: instead of passing raw
pointer to stack memory with all safety concerns associated with it, it
can be wrapped into a MemorySegment before returning it to the user and
on a way back closed, thus effectively forbidding any illegal accesses
(both temporal and spatial) and in completely transparent way:
<R> R withSegmentOnStack(long size, Function<MemorySegment,R> task);
As a performance optimization, JIT can then intrinsify the native method
and directly allocate memory on stack without the need for auxiliary
native frame. It'll provide alloca-like behavior while considerably
simplifying JVM support.
It definitely looks very interesting in the context of low-level ABI and
native invokers, but IMO stack allocation is not a prerequisite for
Memory Access API and the API shouldn't wait for it to be released.
After there's more data available from ABI experiments, we'll be in a
better position to decide how to proceed (either add it to Memory Access
API, build a separate API on top, or even drop it).
Best regards,
Vladimir Ivanov
More information about the core-libs-dev
mailing list