urt-rs / docs /research /COLLISION_COMPOSITION.md
nmarshall's picture
Recover collision copy status and world-result composition
7689014
|
Raw History Blame Contribute Delete
6.04 kB
# Collision copy/status composition and world-result decisions
Static pass, 2026-10-11. Reproduce with `python3 scripts/analyze_collision_composition.py`; check with `python3 scripts/test_collision_composition.py`. [Generated evidence](collision-composition.json) verifies original/disassembly hashes for both Linux ELF64 engines, retains clip/trace graphs, and records **216 complete bounded merge/copy slices plus twelve world-result decisions**. No original process, intersection generator or collision callee executes. This extends the [first-lane decision findings](NATIVE_COLLISION.md).
## MIX-001: three unrolled result lanes
SV_ClipMoveToEntities has three post-CM_TransformedBoxTrace lanes. The collector identifies each candidate status read and finite fraction comparison, then evaluates the original instructions through the lane's common continuation address. Lane 1 uses candidate register r12; lanes 0/2 use rbp. Register renaming and out-of-line branches are followed rather than treated as separate algorithms.
Each engine has 108 slices: all three lanes, candidate status words 0/1 at result offsets 0/4, candidate fraction **0.25/0.5/0.75**, prior current fraction **0.5**, and prior offset-4 word **0/1/4**. The input's other result words contain distinct old/new payload markers; old identifier is 42 and candidate object word zero is 7. Initial current offset-0 status is zero. Prior status value 4 is a synthetic raw-bit case, not a claim that normal engine status values include 4.
All three lanes produce the same final words for every tested input. They replace only when candidate fraction is **strictly smaller**. Equal and farther fractions preserve current fraction, payload and identifier. Candidate flags may still update the current status words before that comparison. These probes establish bounded lane agreement, not the entire unrolled loop's entry, scheduling or early-exit behavior.
## MIX-002: byte-addressed copies and accumulated status
The new restricted evaluator uses a byte-addressed memory map, so four-byte OR/store operations and overlapping eight-byte loads/stores share actual fixture bytes. It handles only the observed moves, register aliases, selected integer/finite SSE comparisons, status writes and branches. Unknown reads/operations, nonfinite comparisons and step limits fail closed. It models 32-bit register writes clearing upper bits, and AL writes preserving the remaining RAX bits; tests cover both.
Let C0/C4 denote candidate status words, P4 the prior current offset-4 word, and F the candidate fraction. In the tested domain, the status update before deciding on replacement is:
```
intermediate4 = P4 if C0 != 0
1 if C0 == 0 and C4 != 0
P4 otherwise
```
Candidate C0 nonzero separately sets current offset 0 to 1. It skips the candidate C4 test in that lane. Then:
- **F < current fraction:** candidate object word zero is written into candidate result offset **52**; seven eight-byte chunks copy the **56-byte** candidate into current. The saved intermediate4 is ORed into copied candidate offset 4. Final status4 is therefore **C4 OR intermediate4**, with payload and identifier from the candidate.
- **F >= current fraction:** no full copy occurs. The current payload/identifier remain unchanged; status updates made before the comparison survive.
A raw prior status4 of 4 plus candidate C4=1 can produce 5 after a closer hit. A zero candidate C4 does not erase a prior status4 on replacement. When C0 is nonzero, the candidate C4 contribution can enter through copying even though its separate pre-copy test was skipped. These differences matter when separating hit selection from status accumulation.
Distinct marker words verify complete payload transfer and retention. Canaries directly before/after the current result span stay unchanged in all slices, and each closer-hit path makes seven eight-byte writes totaling 56 bytes plus its status/identifier operations. This is an observed copy span, not proof of ABI member names, all object memory bounds or atomicity.
## MIX-003: world identifier and entity-clipping gate
A separate slice in SV_Trace begins after CM_BoxTrace and its file-backed 1.0 load, supplying the returned fraction and xmm2 constant explicitly. It follows the original single-precision compare, SETE low-byte write, integer add and subsequent zero comparison.
The world-result identifier at relative result offset **52** becomes:
```
1023 if returned fraction == 1.0
1022 otherwise
```
The fraction is then compared with zero. **+0.0 and -0.0** take the branch directly toward result copying, skipping the later entity-clipping path. Other tested finite values continue into swept-bound/entity clipping. Inputs 0.25/1.0/1.5/-1.0 exercise identifier and continuation distinctions; 1.5/-1.0 are synthetic out-of-normal-range cases, not evidence that CM_BoxTrace produces them in gameplay.
The graph labels and constants establish identifier assignment and continuation, without executing world collision or assigning every sentinel's complete lifecycle. The zero branch is separate from the clip helper's status-driven early exits. COMISS exceptional flags, NaN behavior, native libm/rounding domains and collision producer constraints remain unmodeled.
## Remaining work and Rust dependencies
RE-293–295 record three-lane composition, byte-copy/status behavior and world-result decisions. RE-292 remains open for complete clipping loops and geometry; RE-296 tracks full multi-candidate/world/entity composition, prior nonzero offset-0 reachability, every early-exit/count path, canonical status/fraction producers, final trace field/sentinel identities, exceptional floating-point behavior and original-runtime/all-platform fixtures. Rust collision results need independent payload selection and status accumulation, followed by the recovered world/entity scheduling rules; the tested slices alone are not a complete collision implementation.