aboutsummaryrefslogtreecommitdiff
path: root/docs/history/18-aliases/notes.md
blob: eb0afc0ce8e7513bc84bf3febc2e45849e5cbe2b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
# tracked aliases

the open end was untracked aliases: `let q = p + 0` or `let c = list[1]` became a plain word, and it dangled once the owner was freed.

## what landed

the analyzer reuses the child link. a pointer-typed value computed from a tracked variable is stored as `S_CHILD` with no `lown` bit: `p + k` and `p - k` (not a pointer difference), `p.field` when the field is a pointer, and `p[i]` when the element is a pointer. untyped `p + k` on an owned object counts too, since that variable is a pointer even when its type is still `word`. using the alias after the owner dies is the same error a child already gets, "used after it was given away". an alias is not an owner, so it can be copied, incremented and passed on, and the scope-end free doesn't free it. an alias that outlives the block its owner was declared in is marked dead when that block closes.

`free` no longer returns the block to the buddy lists. it leaves the header marked free and the check word in place, so `isobj` fails and a second free is a no-op, but the bytes stay. the mark treats a word with that check word and a free flag as a quarantined object and traces it. the sweep merges a quarantined block back only when nothing pointed at it. a reachable one stays quarantined, still intact. the compiler zeros a local after the free it inserts, and `start` scrubs the data stack and collects once compilation is done, so the compiler's own garbage doesn't sit on the heap forever.

## tests

`tests/alias.zc` uses an alias while the owner is alive (arithmetic, a pointer field, an index). `tests/errors/alias_plus.zc`, `alias_index.zc`, `alias_field.zc` and `alias_scope.zc` are the uses after the owner dies. `tests/quarantine.zc` is unchecked: after `free`, churn that would have reused the block, the old words are still there, `free` through the alias doesn't smash them, and a collection while an exact pointer is still live keeps the block. an interior pointer (`p + k` with `k` not zero) does not match the check word, so a later collection reclaims that block; exact pointers (`p + 0`, a pointer field, a pointer element) keep it. an untyped index stays a plain word, since the element might be an integer, and quarantine is what covers that case.