Skip to content

Commit 572b978

Browse files
committed
docs(jit): document script inlining conditions
1 parent 446741d commit 572b978

1 file changed

Lines changed: 26 additions & 0 deletions

File tree

content/docs/reference/rustscript/jit-aot.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,32 @@ Trace JIT follows a LuaJIT-style hot-loop model:
4949

5050
A backward `brfalse` can remain inside a trace as a loop back-edge when its target already exists in the recorded trace. Backward targets outside the trace become side exits.
5151

52+
### Short script-function inlining
53+
54+
When the recorder encounters `callvalue` while compiling a hot parent trace, it can merge one short script function into the parent's SSA trace. Inlining has no separate call-count threshold: the parent loop, exit, or continuation must first become hot. The default hot-loop threshold is 8.
55+
56+
The call site is eligible only when all of these conditions hold:
57+
58+
- The caller is the root frame. Calls made from a callable frame are not currently inlined.
59+
- The callable value can be traced to a root local with exactly one static callable binding.
60+
- The callable prototype observed in that local at trace entry matches the statically selected prototype. A changed target follows the regular `callvalue` path.
61+
- The target is an uncaptured `FunctionItem` backed by a RustScript `ScriptFunction`; closures, captured functions, and host callables are excluded.
62+
- The call arity, prototype arity, and parameter-slot metadata agree.
63+
- The target is not recursive, and the recorder is not already inside another inlined function. Current inline depth is one.
64+
- The callee and parent together fit within `max_trace_len`, whose default is 256 decoded operations.
65+
66+
The callee body must also satisfy these bounds:
67+
68+
- At most 32 decoded instructions, including the final `ret`.
69+
- At most 8 distinct local slots read or written.
70+
- Exactly one `ret`, at the end of the function region.
71+
- Forward `br` and `brfalse` targets may stay within the region. Backward branches, and therefore callee loops, are rejected.
72+
- Nested `callvalue` is rejected. A bytecode `call` is accepted only for a recognized builtin with valid arity; final recorder and native-lowering support is still required.
73+
74+
If the callable has no schema, it needs no argument-schema guard. With a callable schema, parameter count must match and every parameter must either be proven by the recorded SSA representation or support a runtime type guard. Current guards cover `int`, `float`, `bool`, `string`, `bytes`, arrays, and map/object-like values. `Unknown` and generic parameters impose no guard. `null`, `number`, `optional`, and callable parameter schemas currently reject inlining. A failed runtime guard exits at the original `callvalue` instruction so the interpreter performs the call.
75+
76+
Call-site target profiles and inline counters are exposed for diagnostics, but profile observation counts do not add another admission threshold. Native trace entry and inherited-state handoff are also suppressed while the active frame has shared `Borrow` or `BorrowMut` capture cells, since those cells are authoritative over raw local snapshots.
77+
5278
Configure or inspect tracing with:
5379

5480
- `vm.set_jit_config(...)`

0 commit comments

Comments
 (0)