docs(context): fix off-by-one-slot error in init_actor_stack layout comment

The diagram claimed the entry/ret target sits at aligned_top-8 and r15 at
aligned_top-56. The code does (top & ~15) - 8 then a -= 8 before the first
write, so entry actually lands at aligned_top-16 and r15 at aligned_top-64.
Confirmed by single-stepping the shim's ret under llmdbg: the entry slot is
at an address with %16==0, giving the required rsp%16==8 on entry. Code was
correct; only the comment was wrong (and would mislead a maintainer).
This commit is contained in:
smarm-dev
2026-05-28 05:50:18 +00:00
parent 594392a5ae
commit 6d17254ae3
+19 -11
View File
@@ -24,18 +24,26 @@ pub fn set_actor_sp(v: usize) { ACTOR_SP.with(|c| c.set(v)) }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Initial stack layout // Initial stack layout
// //
// After alignment, sp = top & ~15 - 8. Then we push (downward) six callee- // We start from aligned_top = top & ~15, then bias by 8 and push seven 8-byte
// saved register slots and a return address. The first `switch_to_actor` // slots (downward). The first `switch_to_actor` pops r15..rbx and `ret`s —
// pops r15..rbx and `ret`s — landing in `entry` with rsp % 16 == 8. // landing in `entry` with rsp % 16 == 8 (the x86-64 ABI state at the point
// just after a `call`, which is what `entry` is compiled to expect).
// //
// Layout (high → low), relative to aligned_top = top & ~15: // Layout (high → low), relative to aligned_top = top & ~15. Note the entry
// aligned_top - 8 : entry ptr ← `ret` target. Post-ret: rsp % 16 == 8. // slot is at aligned_top - 16, NOT aligned_top - 8: the function does
// aligned_top - 16 : rbx = 0 // `(top & ~15) - 8` and *then* a `-= 8` before the first write, so the first
// aligned_top - 24 : rbp = 0 // stored word lands at aligned_top - 16. Verified by single-stepping the
// aligned_top - 32 : r12 = 0 // `ret` under llmdbg: entry sits at an address with %16 == 0, so the post-ret
// aligned_top - 40 : r13 = 0 // rsp is %16 == 8.
// aligned_top - 48 : r14 = 0 //
// aligned_top - 56 : r15 = 0 ← initial rsp // aligned_top - 8 : (unused padding; keeps entry's slot %16 == 0)
// aligned_top - 16 : entry ptr ← `ret` target. Post-ret: rsp % 16 == 8.
// aligned_top - 24 : rbx = 0
// aligned_top - 32 : rbp = 0
// aligned_top - 40 : r12 = 0
// aligned_top - 48 : r13 = 0
// aligned_top - 56 : r14 = 0
// aligned_top - 64 : r15 = 0 ← initial rsp
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
pub fn init_actor_stack(top: *mut u8, entry: extern "C-unwind" fn()) -> usize { pub fn init_actor_stack(top: *mut u8, entry: extern "C-unwind" fn()) -> usize {