Skip to content

Tail call opt#26

Merged
andreaTP merged 7 commits into
roastedroot:mainfrom
andreaTP:tail-call-opt
May 5, 2026
Merged

Tail call opt#26
andreaTP merged 7 commits into
roastedroot:mainfrom
andreaTP:tail-call-opt

Conversation

@andreaTP
Copy link
Copy Markdown
Contributor

Inspired by: dylibso/chicory#1284

andreaTP and others added 7 commits May 5, 2026 11:59
Track the gap between Chicory's supported proposals and Redline's
current coverage so contributors can see at a glance what remains.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Switch all functions to CallConv::Tail and enable preserve_frame_pointers
so Cranelift emits true tail calls that reuse the caller's stack frame.
This means deeply recursive tail calls won't overflow the stack — unlike
JVM bytecode desugaring which would still be limited by JVM stack depth.

Adds return_call and return_call_indirect opcodes, passing all 119 spec
tests (including stack-overflow stress tests). JMH benchmarks confirm no
performance regression from the calling convention change.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Java FFI (Panama/jffi) always uses the platform C ABI, but compiled wasm
functions use CallConv::Tail. On x86_64 Linux these happen to use the
same registers (SystemV), but on Windows and aarch64 the mismatch causes
crashes.

Add Cranelift-compiled ABI trampolines on all platforms:
- Entry trampolines (platform ABI -> Tail) for Java-to-wasm calls
- Import trampolines (Tail -> platform ABI) for wasm-to-Java callbacks

The Rust bridge gains trampoline compilation exports that build thin
wrapper functions using Cranelift's cross-convention call_indirect.
Entry trampolines take an extra funcPtr parameter (bound via
MethodHandles.insertArguments / shifted jffi args). Import trampolines
bake in the upcall stub address via iconst.

Multi-value return functions use a single i64 return in the trampoline
signature, matching the compiler's convention of storing extras in the
args buffer.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…rampolines

The call_indirect dispatch stub, memory.grow stub, and libc memmove/memset
are all called from Tail-convention compiled wasm code but use the
platform C ABI. This caused JVM crashes on aarch64 and Windows where the
ABIs differ.

Wrap each stub with a Cranelift-compiled import trampoline (Tail ->
platform ABI) and store the trampoline address in ctxBuffer instead of
the raw stub address.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move duplicated trampoline code from NativeMachine, JffiNativeMachine,
and EmitContext into RedlineBridge:

- valTypeToBridgeType: was duplicated in 3 files
- buildTrampolineSig, compileEntryTrampoline(FunctionType),
  compileImportTrampoline(FunctionType, long), compileStubTrampoline:
  were duplicated in both runners
- compileTrampolines: new orchestration method that compiles all
  trampolines (entry, import, internal stubs) in one call
- CompiledTrampolines: result object returned by compileTrampolines
- align: utility method moved from both runners

Net -88 lines, eliminating all trampoline compilation duplication.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove dead createDowncall (replaced by createDowncallViaTrampoline)
- Remove dead callContexts, createCallContext, invokeNative,
  invokeViaBuffer (replaced by entry trampoline dispatch)
- Fix fragile back-subtraction for entry trampoline address: record
  address before copy instead of computing it after
- Extract compile_trampoline helper and copy_sig in Rust to eliminate
  duplicated FunctionBuilder/compile boilerplate between entry and
  import trampolines

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The refactoring that moved valTypeToBridgeType to RedlineBridge
changed the exception from UnsupportedOperationException to
ChicoryException. This broke UnsupportedOpcodeTest which asserts
the root cause is UnsupportedOperationException (e.g. for SIMD v128
types that hit valTypeToBridgeType before the opcode switch).

Restore the original exception type.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@andreaTP andreaTP merged commit c50e55d into roastedroot:main May 5, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant