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

Reply via email to