perf(ir): lower nested writes through a boxed list as one call of List.update #238
Loading…
Reference in a new issue
No description provided.
Delete branch "loop/207-update-lowering"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #207
Task
#207: a nested write through a list that stayed boxed (trait-typed) after the devirtualization still went through the round trip of
Index.atandMutableIndex.seton the witness table, so the element was owned twice while it changed and the change copied it. #215 gaveArrayListandTrieListanupdateof their own; this is the other half, the lowering.What and why
compiler/src/ir/updates.trb(new): an IR pass after the element steps (rewriteElementPlaces,dropProvableChecks) and before ownership. It finds the round trip in one block -read C,callWitness at(key)into the element, the rest of the path on the element,makeUnique C,callWitness set(key, element)- and writes it ascallWitness update(key, closure)onC, whose closure takes the element by reference and runs the rest of the path on it.updatechecks the key before it calls the closure, so an index out of range panics with the message ofatbefore the rest of the path runs - the same output as before (tests/conformance/list-update-bounds.trb).varparameter, the list's own slot; noremoveAt/insert, nothing taken out and put back.List.update(found by symbol in the witness table, one per table) is trusted; only plain functions; a window that branches, holds a debug statement, reads avarparameter, dispatches on a generic parameter's witness, or whose values are used after the put-back is left as it was.compiler/src/ir/lower/lower.trb: wires the pass in and findsat,setandupdateof everyListwitness table.compiler/src/ir/elements.trb: makes the helpers the pass shares public.compiler/README.md.No new native, no change to
std/, so no seed step.Test
tests/conformance/list-update-nested.trb: the evaluation order of keys and value through two boxed lists on one path (a list in a list field, a list of lists), a captured local, a write that reads the element (types[1] = types[1] * 10), an interpolated write, and that a copy taken before the write keeps its value. Expected output generated withmain's binary.tests/conformance/list-update-bounds.trb: out of range panics at the site with the message ofat, and nothing after the access is evaluated (.stderr, exit 101). Expected output generated withmain's binary.compiler/tests/boxed-updates.test.trb: snapshots the loweredwrite(onecallWitnessof memberupdate, noat, nosetof the element) and its closure, and that the nested program verifies before and after ownership with five closures. Passes locally in the VM.Measurement
Forge CI, job
measure-207on the throwaway branchloop/207-measure:main(91c009ff) and this change bootstrapped on the same runner, run alternately, 3 runs each, processor time, mean (PERFORMANCE 9.11):torb check tests/conformance/adts.trbtorb build --emit-c tests/conformance/adts.trbtorb build --emit-c ./compilerNeutral within the noise (runs of one case differ by up to 9%): the write that cost the front end was already an
ArrayListfield after round one. The gain is the element copy avoided in programs that write through aListthat stays boxed. The same job ran both new conformance programs on the new binary: same stdout and exit code asmain.Approved at
20872b48. CI green on this head (bootstrap, tier A and B, same-C-on-every-host, pdisc).at(exit 101,.stderr).boxed-updates.test.trbpins the loweredwrite(oneupdatecall, noat/set) and its closure, and that the nested program verifies before and after ownership.at/makeUnique/setshape, an own-access check on the receiver and element, a movable-only window, and capturable-by-value outer slots; anything else keeps the round trip. Onlystd/'supdateis trusted, and tables that disagree are refused. The closure is created at the oldRead, so the key and everything evaluated earlier stay outside and are captured as values; this matches BACKEND 2.3.std/change, no native, so no seed step.Non-blocking:
var-parameter read, or a use of the element after the put-back staying the round trip). A short snapshot test of one refused shape would guard the conservative side against a later loosening ofisMovableorisCapturable.Listwould give the claim a number in 9.11.Windowandwindows(CONCURRENCY slice F, gap 6) #4