JIT miscompiles untyped function parameters as zero after RECV elision
- Dominant language
- Rust
- Stars
- 13
- Forks
- 0
- PR merge metrics
- No merged PRs in 30d
Description
## Summary
The whole-function JIT can compile functions with untyped integer arguments, but their parameter CV slots are initialized to zero instead of receiving the runtime arguments.
This produces silently incorrect results.
Tested at commit `67ef61e68048a2a508cae3bb0834cfe69863fe46` on Linux x86_64 with Rust 1.96.0.
## Current JIT build blocker
At this commit, `cargo build --release --features jit` first fails because `jit_loop_hook()` uses `ctx` without receiving it.
For runtime testing, I applied only the mechanical wiring fix:
```diff
-pub(crate) fn jit_loop_hook(&mut self, idx: usize, header: usize, end: usize)
+pub(crate) fn jit_loop_hook(&mut self, ctx: &mut RunCtx, idx: usize, header: usize, end: usize)
```
and:
```diff
-vm.jit_loop_hook(idx, cur, end);
+vm.jit_loop_hook(ctx, idx, cur, end);
```
No JIT logic was otherwise changed.
## Reproducer
```php
add1(0) => 1
double($x) => double(0) => 0
```
Each `combine()` call therefore returns `1`, explaining the observed total of exactly `5000000`.
The existing parameter JIT test uses a typed parameter:
```php
function kern(int $n): int
```
That form retains `RECV`, so it does not exercise the compiler/JIT mismatch for untyped parameters.
## Possible fixes
A conservative short-term fix would be to reject whole-function JIT compilation when a parameter has no corresponding `RECV`.
A more complete fix would initialize parameter CV slots from `args_ptr` using the op-array parameter/CV metadata, independently of whether the interpreter bytecode retained `RECV`.
It would also be useful to add an integration test that goes through the normal compiler and VM call path with an untyped function receiving runtime integer arguments.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start by running cargo build --release --features jit and inspect is_int_only(), translate(), jit_loop_hook(), and Opcode::Recv handling. Trace how untyped parameters reach JIT CV slots, then add an integration test through the normal compiler and VM call path using the reproducer's runtime integer arguments. Done means the JIT result matches the non-JIT expected total.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- php, rust
- Domain
- compilers, testing-qa
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100