I'm working on a compiler to produce a WASM image from a Java program. One of the challenges is that Java supports multiple threads; because of the unsuitability (and lack of availability) of the current Host GC proposal, we're looking at maintaining shadow stacks for each thread in order to perform in-image GC. The difficulty is one of memory management: typically a Java runtime would allocate many discontiguous regions from virtual memory to facilitate multiple downward-growing stacks and a typically upwards-growing heap, relying on the operating system to ensure that the gaps and unused areas in these regions don't consume physical memory resources. However WASM memory can seemingly only grow in one contiguous blob, which would imply that things need to be densely packed in order to avoid excessive memory usage. I was wondering if there are any discussions on how folks are handling this kind of situation?
I work on the ghc wasm backend and had a similar challenge before. The haskell runtime used to assume existence of mmap/VirtualAlloc. I ended up refactoring it to optionally support grabbing memory via sbrk, maybe similar refactorings can also be done for java?
You might want to look at how TeaVM does it, e.g. https://github.com/konsoletyper/teavm/blob/a543b91b84bef71f0c4d60c5a1073f133963779f/core/src/main/java/org/teavm/runtime/Fiber.java. I haven't studied it in detail, but it appears to be using heap-allocated, dynamically resized arrays for each primitive and reference type. Another option would be to support a segmented stack with fixed-sized segments which are allocated and freed as needed.
BTW, I think Java developers know to expect size-limited stacks by now, so if you anticipate that the number of threads per app is going to be relatively low, and that memory is not particularly constrained, you could keep it simple and just allocate a fixed-sized stack (e.g. 512KB) per thread, generating a StackOverflowError
if it overflows.
Last updated: Dec 23 2024 at 12:05 UTC