Expand description
Ground-truth effect-atom recorder (issue #870, T2 effects epic,
docs/effects-spec.md). The effects analogue of the oracle: this module
records, per executing definition scope, the atomic effects the VM
actually performs — cells read, cells written, external kinds called —
so brink-test-harness can assert the statically-inferred effects(def)
row (brink-db::ProjectDb::effects) covers every one of them for every
def a real run executed. A purely structural inter-row consistency check
(caller’s row ⊇ callee’s row) cannot catch an under-report where both
rows silently agree on the wrong (too-small) answer — exactly the #866
ref-param-write regression this issue is named for. This is the
independent, run-the-bytecode-and-look check that closes that gap.
Attribution mirrors the static analyzer’s own model exactly
(brink_analyzer::infer::body::record_ref_param_writes), not naively
“whichever def’s bytecode happens to be executing”: a ref argument’s
pointer/projection is constructed exactly once, at the call site, inside
the caller’s own bytecode (Opcode::PushVarPointer/Opcode:: MakeProjection — both are emitted only there, never for a plain read,
confirmed against brink-codegen-inkb’s expr.rs). The eventual
dereference deep inside the callee’s frame (SetTemp/GetTemp/
TakeTemp’s pointer/projection arms, ProjRead/ProjWrite) is
deliberately not re-recorded — the callee’s own row is generic over
whichever concrete cell a caller bound its ref parameter to, so the
static model charges the write to the call site that names the concrete
global, never to the callee. Recording at construction time reproduces
that attribution for free: whichever def’s bytecode is running when the
pointer/projection value is built is, by construction, the def the
static analyzer also charges. See the call sites in vm.rs’s
note_effect_* helpers for the exact opcodes instrumented.
Feature-gated exactly like the bench-counters module (issue #821):
this module and every call site are compiled out entirely unless
effect-trace is enabled (not part of default — no released consumer
should ever turn it on), so an ordinary build pays exactly zero cost.
Structs§
- Observed
Row - Atoms observed for one executed definition scope (
docs/effects-spec.md§2) — the runtime counterpart ofbrink_analyzer::EffectRow’s{reads, writes, calls}(this module never constructs an opaque row: every atom the VM performs is concrete).
Functions§
- is_
tracked_ fault - NS-A2 (issue #1108, from #1097): is this error one of the designed
domain faults the
faultsrow dimension tracks? The inventory mirrors the static harvest inbrink-analyzer::infer::bodyexactly — every variant listed here must be raisable only by a construct that sets the staticfaultsbit (indexing,//mod, the faulting stdlib intrinsics, conversions,refprojections, value calls), or the ground-truth harness would report a false under-report. - record_
call - Record an external-kind call, attributed to
def. - record_
emit - NS-A2 (issue #1108): record a visible content emission, attributed to
def. - record_
fault - NS-A2: record a tracked turn-terminating fault, attributed to
def(the definition scope executing whenvm::stepreturned the fault). - record_
read - Record a cell read, attributed to
def(the definition scope executing when the read happened — see the module docs for what “attributed to” means for a pointer/projection-mediated access). - record_
tag - NS-A2: record a tag-channel touch, attributed to
def. - record_
write - Record a cell write, attributed to
def. - reset
- Clear every recorded atom. Call before each measured run — the recorder is a single process-wide map, so a caller driving multiple programs (or multiple explored episodes of one program) in the same process must reset between the units it wants to compare independently.
- snapshot
- Snapshot every def’s observed atoms recorded since the last
reset.