FA-90451 / Garbage collector invariants / Open access
Sliding compaction: pointers to object starts resolve to the previous object · case 01
References to an object's first byte are reported as dangling or attributed to its neighbour.
ROOT CAUSE
bisect_left excludes an object whose start equals the pointer.
VERIFIED REPAIR
Use the last object whose start is <= the pointer.
Unsuccessful approach: Taking the bisect_left index attributes interior pointers to the next object.
Case contract
Mark-compact with sliding. objs are [start, size, fields] in arbitrary order; pointers (fields and roots) may point anywhere inside an object and belong to the object whose [start, start+size) contains them; a pointer outside every object is ["dangling-pointer", p]. Mark from the roots, assign new addresses to live objects in address order starting at base with no gaps, and relocate every pointer to new start + original offset. Return the new layout [new, old, fields], new roots and the new top.
Why this case matters
Sliding compaction must preserve address order and interior offsets while squeezing out dead space.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import bisect
N = 1
observations = []
def solve(objs, roots, base):
starts = sorted(o[0] for o in objs)
info = {o[0]: o for o in objs}
def owner(p):
i = bisect.bisect_left(starts, p) - 1
if i < 0:
raise KeyError(p)
s = starts[i]
if p >= s + info[s][1]:
raise KeyError(p)
return s
try:
live = set()
stack = [r for r in roots if r is not None]
while stack:
s = owner(stack.pop())
if s in live:
continue
live.add(s)
stack.extend(f for f in info[s][2] if f is not None)
fwd = {}
top = base
for s in starts:
if s in live:
fwd[s] = top
top += info[s][1]
def reloc(p):
if p is None:
return None
s = owner(p)
return fwd[s] + (p - s)
layout = [[fwd[s], s, [reloc(f) for f in info[s][2]]] for s in starts if s in live]
new_roots = [reloc(r) for r in roots]
except KeyError as e:
return ['dangling-pointer', e.args[0]]
except IndexError:
return ['heap-walk-error']
return {'layout': layout, 'roots': new_roots, 'top': top}
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = [[('regression: interior pointers relocate with their object',
([[160, 16, []], [100, 16, [133, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [100], 100),
{'layout': [[100, 100, [125, None]], [116, 124, [104]]], 'roots': [100], 'top': 140}),
('dead objects do not advance the compaction pointer',
([[160, 16, []], [100, 16, [133, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [124], 100),
{'layout': [[100, 100, [125, None]], [116, 124, [104]]], 'roots': [116], 'top': 140}),
('pointer to an object start',
([[160, 16, []], [100, 16, [133, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]],
[148, 160],
100),
{'layout': [[100, 148, [112]], [112, 160, []]], 'roots': [100, 112], 'top': 128}),
('interior root',
([[160, 16, []], [100, 16, [133, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [151], 100),
{'layout': [[100, 148, [112]], [112, 160, []]], 'roots': [103], 'top': 128}),
('compaction into a lower base',
([[160, 16, []], [100, 16, [133, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]],
[100, 148],
41),
{'layout': [[41, 100, [66, None]], [57, 124, [45]], [81, 148, [93]], [93, 160, []]],
'roots': [41, 81],
'top': 109}),
('control: no roots',
([[160, 16, []], [100, 16, [133, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [None], 100),
{'layout': [], 'roots': [None], 'top': 100})],
[('regression: interior pointers relocate with their object',
([[160, 16, []], [100, 16, [134, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [100], 100),
{'layout': [[100, 100, [126, None]], [116, 124, [104]]], 'roots': [100], 'top': 140}),
('dead objects do not advance the compaction pointer',
([[160, 16, []], [100, 16, [134, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [124], 100),
{'layout': [[100, 100, [126, None]], [116, 124, [104]]], 'roots': [116], 'top': 140}),
('pointer to an object start',
([[160, 16, []], [100, 16, [134, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]],
[148, 160],
100),
{'layout': [[100, 148, [112]], [112, 160, []]], 'roots': [100, 112], 'top': 128}),
('interior root',
([[160, 16, []], [100, 16, [134, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [152], 100),
{'layout': [[100, 148, [112]], [112, 160, []]], 'roots': [104], 'top': 128}),
('compaction into a lower base',
([[160, 16, []], [100, 16, [134, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]],
[100, 148],
42),
{'layout': [[42, 100, [68, None]], [58, 124, [46]], [82, 148, [94]], [94, 160, []]],
'roots': [42, 82],
'top': 110}),
('control: no roots',
([[160, 16, []], [100, 16, [134, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [None], 100),
{'layout': [], 'roots': [None], 'top': 100})],
[('regression: interior pointers relocate with their object',
([[160, 16, []], [100, 16, [135, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [100], 100),
{'layout': [[100, 100, [127, None]], [116, 124, [104]]], 'roots': [100], 'top': 140}),
('dead objects do not advance the compaction pointer',
([[160, 16, []], [100, 16, [135, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [124], 100),
{'layout': [[100, 100, [127, None]], [116, 124, [104]]], 'roots': [116], 'top': 140}),
('pointer to an object start',
([[160, 16, []], [100, 16, [135, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]],
[148, 160],
100),
{'layout': [[100, 148, [112]], [112, 160, []]], 'roots': [100, 112], 'top': 128}),
('interior root',
([[160, 16, []], [100, 16, [135, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [153], 100),
{'layout': [[100, 148, [112]], [112, 160, []]], 'roots': [105], 'top': 128}),
('compaction into a lower base',
([[160, 16, []], [100, 16, [135, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]],
[100, 148],
43),
{'layout': [[43, 100, [70, None]], [59, 124, [47]], [83, 148, [95]], [95, 160, []]],
'roots': [43, 83],
'top': 111}),
('control: no roots',
([[160, 16, []], [100, 16, [135, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [None], 100),
{'layout': [], 'roots': [None], 'top': 100})],
[('regression: interior pointers relocate with their object',
([[160, 16, []], [100, 16, [136, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [100], 100),
{'layout': [[100, 100, [128, None]], [116, 124, [104]]], 'roots': [100], 'top': 140}),
('dead objects do not advance the compaction pointer',
([[160, 16, []], [100, 16, [136, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [124], 100),
{'layout': [[100, 100, [128, None]], [116, 124, [104]]], 'roots': [116], 'top': 140}),
('pointer to an object start',
([[160, 16, []], [100, 16, [136, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]],
[148, 160],
100),
{'layout': [[100, 148, [112]], [112, 160, []]], 'roots': [100, 112], 'top': 128}),
('interior root',
([[160, 16, []], [100, 16, [136, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [150], 100),
{'layout': [[100, 148, [112]], [112, 160, []]], 'roots': [102], 'top': 128}),
('compaction into a lower base',
([[160, 16, []], [100, 16, [136, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]],
[100, 148],
44),
{'layout': [[44, 100, [72, None]], [60, 124, [48]], [84, 148, [96]], [96, 160, []]],
'roots': [44, 84],
'top': 112}),
('control: no roots',
([[160, 16, []], [100, 16, [136, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [None], 100),
{'layout': [], 'roots': [None], 'top': 100})],
[('regression: interior pointers relocate with their object',
([[160, 16, []], [100, 16, [137, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [100], 100),
{'layout': [[100, 100, [129, None]], [116, 124, [104]]], 'roots': [100], 'top': 140}),
('dead objects do not advance the compaction pointer',
([[160, 16, []], [100, 16, [137, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [124], 100),
{'layout': [[100, 100, [129, None]], [116, 124, [104]]], 'roots': [116], 'top': 140}),
('pointer to an object start',
([[160, 16, []], [100, 16, [137, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]],
[148, 160],
100),
{'layout': [[100, 148, [112]], [112, 160, []]], 'roots': [100, 112], 'top': 128}),
('interior root',
([[160, 16, []], [100, 16, [137, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [151], 100),
{'layout': [[100, 148, [112]], [112, 160, []]], 'roots': [103], 'top': 128}),
('compaction into a lower base',
([[160, 16, []], [100, 16, [137, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]],
[100, 148],
45),
{'layout': [[45, 100, [74, None]], [61, 124, [49]], [85, 148, [97]], [97, 160, []]],
'roots': [45, 85],
'top': 113}),
('control: no roots',
([[160, 16, []], [100, 16, [137, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [None], 100),
{'layout': [], 'roots': [None], 'top': 100})]]
for label, args, expected in cases[N - 1]:
check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression: interior pointers relocate with their object | ['dangling-pointer', 100] | {'layout': [[100, 100, [125, None]], [116, 124, [104]]], 'roots': [100], 'top': 140} | Failed |
| dead objects do not advance the compaction pointer | ['dangling-pointer', 124] | {'layout': [[100, 100, [125, None]], [116, 124, [104]]], 'roots': [116], 'top': 140} | Failed |
| pointer to an object start | ['dangling-pointer', 160] | {'layout': [[100, 148, [112]], [112, 160, []]], 'roots': [100, 112], 'top': 128} | Failed |
| interior root | ['dangling-pointer', 160] | {'layout': [[100, 148, [112]], [112, 160, []]], 'roots': [103], 'top': 128} | Failed |
| compaction into a lower base | ['dangling-pointer', 148] | {'layout': [[41, 100, [66, None]], [57, 124, [45]], [81, 148, [93]], [93, 160, []]], 'roots': [41, 81], 'top': 109} | Failed |
| control: no roots | {'layout': [], 'roots': [None], 'top': 100} | {'layout': [], 'roots': [None], 'top': 100} | Passed |
SHA-256 / eceba023c0bc7574e65284f04f8c40a141d0ab00739c4cc1c3e7b4e3db794210
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import bisect
N = 1
observations = []
def solve(objs, roots, base):
starts = sorted(o[0] for o in objs)
info = {o[0]: o for o in objs}
def owner(p):
i = bisect.bisect_left(starts, p)
if i < 0:
raise KeyError(p)
s = starts[i]
if p >= s + info[s][1]:
raise KeyError(p)
return s
try:
live = set()
stack = [r for r in roots if r is not None]
while stack:
s = owner(stack.pop())
if s in live:
continue
live.add(s)
stack.extend(f for f in info[s][2] if f is not None)
fwd = {}
top = base
for s in starts:
if s in live:
fwd[s] = top
top += info[s][1]
def reloc(p):
if p is None:
return None
s = owner(p)
return fwd[s] + (p - s)
layout = [[fwd[s], s, [reloc(f) for f in info[s][2]]] for s in starts if s in live]
new_roots = [reloc(r) for r in roots]
except KeyError as e:
return ['dangling-pointer', e.args[0]]
except IndexError:
return ['heap-walk-error']
return {'layout': layout, 'roots': new_roots, 'top': top}
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = [[('regression: interior pointers relocate with their object',
([[160, 16, []], [100, 16, [133, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [100], 100),
{'layout': [[100, 100, [125, None]], [116, 124, [104]]], 'roots': [100], 'top': 140}),
('dead objects do not advance the compaction pointer',
([[160, 16, []], [100, 16, [133, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [124], 100),
{'layout': [[100, 100, [125, None]], [116, 124, [104]]], 'roots': [116], 'top': 140}),
('pointer to an object start',
([[160, 16, []], [100, 16, [133, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]],
[148, 160],
100),
{'layout': [[100, 148, [112]], [112, 160, []]], 'roots': [100, 112], 'top': 128}),
('interior root',
([[160, 16, []], [100, 16, [133, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [151], 100),
{'layout': [[100, 148, [112]], [112, 160, []]], 'roots': [103], 'top': 128}),
('compaction into a lower base',
([[160, 16, []], [100, 16, [133, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]],
[100, 148],
41),
{'layout': [[41, 100, [66, None]], [57, 124, [45]], [81, 148, [93]], [93, 160, []]],
'roots': [41, 81],
'top': 109}),
('control: no roots',
([[160, 16, []], [100, 16, [133, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [None], 100),
{'layout': [], 'roots': [None], 'top': 100})],
[('regression: interior pointers relocate with their object',
([[160, 16, []], [100, 16, [134, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [100], 100),
{'layout': [[100, 100, [126, None]], [116, 124, [104]]], 'roots': [100], 'top': 140}),
('dead objects do not advance the compaction pointer',
([[160, 16, []], [100, 16, [134, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [124], 100),
{'layout': [[100, 100, [126, None]], [116, 124, [104]]], 'roots': [116], 'top': 140}),
('pointer to an object start',
([[160, 16, []], [100, 16, [134, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]],
[148, 160],
100),
{'layout': [[100, 148, [112]], [112, 160, []]], 'roots': [100, 112], 'top': 128}),
('interior root',
([[160, 16, []], [100, 16, [134, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [152], 100),
{'layout': [[100, 148, [112]], [112, 160, []]], 'roots': [104], 'top': 128}),
('compaction into a lower base',
([[160, 16, []], [100, 16, [134, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]],
[100, 148],
42),
{'layout': [[42, 100, [68, None]], [58, 124, [46]], [82, 148, [94]], [94, 160, []]],
'roots': [42, 82],
'top': 110}),
('control: no roots',
([[160, 16, []], [100, 16, [134, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [None], 100),
{'layout': [], 'roots': [None], 'top': 100})],
[('regression: interior pointers relocate with their object',
([[160, 16, []], [100, 16, [135, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [100], 100),
{'layout': [[100, 100, [127, None]], [116, 124, [104]]], 'roots': [100], 'top': 140}),
('dead objects do not advance the compaction pointer',
([[160, 16, []], [100, 16, [135, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [124], 100),
{'layout': [[100, 100, [127, None]], [116, 124, [104]]], 'roots': [116], 'top': 140}),
('pointer to an object start',
([[160, 16, []], [100, 16, [135, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]],
[148, 160],
100),
{'layout': [[100, 148, [112]], [112, 160, []]], 'roots': [100, 112], 'top': 128}),
('interior root',
([[160, 16, []], [100, 16, [135, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [153], 100),
{'layout': [[100, 148, [112]], [112, 160, []]], 'roots': [105], 'top': 128}),
('compaction into a lower base',
([[160, 16, []], [100, 16, [135, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]],
[100, 148],
43),
{'layout': [[43, 100, [70, None]], [59, 124, [47]], [83, 148, [95]], [95, 160, []]],
'roots': [43, 83],
'top': 111}),
('control: no roots',
([[160, 16, []], [100, 16, [135, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [None], 100),
{'layout': [], 'roots': [None], 'top': 100})],
[('regression: interior pointers relocate with their object',
([[160, 16, []], [100, 16, [136, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [100], 100),
{'layout': [[100, 100, [128, None]], [116, 124, [104]]], 'roots': [100], 'top': 140}),
('dead objects do not advance the compaction pointer',
([[160, 16, []], [100, 16, [136, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [124], 100),
{'layout': [[100, 100, [128, None]], [116, 124, [104]]], 'roots': [116], 'top': 140}),
('pointer to an object start',
([[160, 16, []], [100, 16, [136, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]],
[148, 160],
100),
{'layout': [[100, 148, [112]], [112, 160, []]], 'roots': [100, 112], 'top': 128}),
('interior root',
([[160, 16, []], [100, 16, [136, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [150], 100),
{'layout': [[100, 148, [112]], [112, 160, []]], 'roots': [102], 'top': 128}),
('compaction into a lower base',
([[160, 16, []], [100, 16, [136, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]],
[100, 148],
44),
{'layout': [[44, 100, [72, None]], [60, 124, [48]], [84, 148, [96]], [96, 160, []]],
'roots': [44, 84],
'top': 112}),
('control: no roots',
([[160, 16, []], [100, 16, [136, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [None], 100),
{'layout': [], 'roots': [None], 'top': 100})],
[('regression: interior pointers relocate with their object',
([[160, 16, []], [100, 16, [137, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [100], 100),
{'layout': [[100, 100, [129, None]], [116, 124, [104]]], 'roots': [100], 'top': 140}),
('dead objects do not advance the compaction pointer',
([[160, 16, []], [100, 16, [137, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [124], 100),
{'layout': [[100, 100, [129, None]], [116, 124, [104]]], 'roots': [116], 'top': 140}),
('pointer to an object start',
([[160, 16, []], [100, 16, [137, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]],
[148, 160],
100),
{'layout': [[100, 148, [112]], [112, 160, []]], 'roots': [100, 112], 'top': 128}),
('interior root',
([[160, 16, []], [100, 16, [137, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [151], 100),
{'layout': [[100, 148, [112]], [112, 160, []]], 'roots': [103], 'top': 128}),
('compaction into a lower base',
([[160, 16, []], [100, 16, [137, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]],
[100, 148],
45),
{'layout': [[45, 100, [74, None]], [61, 124, [49]], [85, 148, [97]], [97, 160, []]],
'roots': [45, 85],
'top': 113}),
('control: no roots',
([[160, 16, []], [100, 16, [137, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [None], 100),
{'layout': [], 'roots': [None], 'top': 100})]]
for label, args, expected in cases[N - 1]:
check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression: interior pointers relocate with their object | {'layout': [[100, 100, [101, None]], [116, 148, [128]], [128, 160, []]], 'roots': [100], 'top': 144} | {'layout': [[100, 100, [125, None]], [116, 124, [104]]], 'roots': [100], 'top': 140} | Failed |
| dead objects do not advance the compaction pointer | {'layout': [[100, 116, []], [108, 124, [88]]], 'roots': [108], 'top': 132} | {'layout': [[100, 100, [125, None]], [116, 124, [104]]], 'roots': [116], 'top': 140} | Failed |
| pointer to an object start | {'layout': [[100, 148, [112]], [112, 160, []]], 'roots': [100, 112], 'top': 128} | {'layout': [[100, 148, [112]], [112, 160, []]], 'roots': [100, 112], 'top': 128} | Passed |
| interior root | {'layout': [[100, 160, []]], 'roots': [91], 'top': 116} | {'layout': [[100, 148, [112]], [112, 160, []]], 'roots': [103], 'top': 128} | Failed |
| compaction into a lower base | {'layout': [[41, 100, [42, None]], [57, 148, [69]], [69, 160, []]], 'roots': [41, 57], 'top': 85} | {'layout': [[41, 100, [66, None]], [57, 124, [45]], [81, 148, [93]], [93, 160, []]], 'roots': [41, 81], 'top': 109} | Failed |
| control: no roots | {'layout': [], 'roots': [None], 'top': 100} | {'layout': [], 'roots': [None], 'top': 100} | Passed |
SHA-256 / 8cf3ebeb33e1ade819f707b5e76860fe5dd9d2cc9b9ec61943bd0484103f56ed
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
import bisect
N = 1
observations = []
def solve(objs, roots, base):
starts = sorted(o[0] for o in objs)
info = {o[0]: o for o in objs}
def owner(p):
i = bisect.bisect_right(starts, p) - 1
if i < 0:
raise KeyError(p)
s = starts[i]
if p >= s + info[s][1]:
raise KeyError(p)
return s
try:
live = set()
stack = [r for r in roots if r is not None]
while stack:
s = owner(stack.pop())
if s in live:
continue
live.add(s)
stack.extend(f for f in info[s][2] if f is not None)
fwd = {}
top = base
for s in starts:
if s in live:
fwd[s] = top
top += info[s][1]
def reloc(p):
if p is None:
return None
s = owner(p)
return fwd[s] + (p - s)
layout = [[fwd[s], s, [reloc(f) for f in info[s][2]]] for s in starts if s in live]
new_roots = [reloc(r) for r in roots]
except KeyError as e:
return ['dangling-pointer', e.args[0]]
except IndexError:
return ['heap-walk-error']
return {'layout': layout, 'roots': new_roots, 'top': top}
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = [[('regression: interior pointers relocate with their object',
([[160, 16, []], [100, 16, [133, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [100], 100),
{'layout': [[100, 100, [125, None]], [116, 124, [104]]], 'roots': [100], 'top': 140}),
('dead objects do not advance the compaction pointer',
([[160, 16, []], [100, 16, [133, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [124], 100),
{'layout': [[100, 100, [125, None]], [116, 124, [104]]], 'roots': [116], 'top': 140}),
('pointer to an object start',
([[160, 16, []], [100, 16, [133, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]],
[148, 160],
100),
{'layout': [[100, 148, [112]], [112, 160, []]], 'roots': [100, 112], 'top': 128}),
('interior root',
([[160, 16, []], [100, 16, [133, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [151], 100),
{'layout': [[100, 148, [112]], [112, 160, []]], 'roots': [103], 'top': 128}),
('compaction into a lower base',
([[160, 16, []], [100, 16, [133, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]],
[100, 148],
41),
{'layout': [[41, 100, [66, None]], [57, 124, [45]], [81, 148, [93]], [93, 160, []]],
'roots': [41, 81],
'top': 109}),
('control: no roots',
([[160, 16, []], [100, 16, [133, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [None], 100),
{'layout': [], 'roots': [None], 'top': 100})],
[('regression: interior pointers relocate with their object',
([[160, 16, []], [100, 16, [134, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [100], 100),
{'layout': [[100, 100, [126, None]], [116, 124, [104]]], 'roots': [100], 'top': 140}),
('dead objects do not advance the compaction pointer',
([[160, 16, []], [100, 16, [134, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [124], 100),
{'layout': [[100, 100, [126, None]], [116, 124, [104]]], 'roots': [116], 'top': 140}),
('pointer to an object start',
([[160, 16, []], [100, 16, [134, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]],
[148, 160],
100),
{'layout': [[100, 148, [112]], [112, 160, []]], 'roots': [100, 112], 'top': 128}),
('interior root',
([[160, 16, []], [100, 16, [134, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [152], 100),
{'layout': [[100, 148, [112]], [112, 160, []]], 'roots': [104], 'top': 128}),
('compaction into a lower base',
([[160, 16, []], [100, 16, [134, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]],
[100, 148],
42),
{'layout': [[42, 100, [68, None]], [58, 124, [46]], [82, 148, [94]], [94, 160, []]],
'roots': [42, 82],
'top': 110}),
('control: no roots',
([[160, 16, []], [100, 16, [134, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [None], 100),
{'layout': [], 'roots': [None], 'top': 100})],
[('regression: interior pointers relocate with their object',
([[160, 16, []], [100, 16, [135, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [100], 100),
{'layout': [[100, 100, [127, None]], [116, 124, [104]]], 'roots': [100], 'top': 140}),
('dead objects do not advance the compaction pointer',
([[160, 16, []], [100, 16, [135, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [124], 100),
{'layout': [[100, 100, [127, None]], [116, 124, [104]]], 'roots': [116], 'top': 140}),
('pointer to an object start',
([[160, 16, []], [100, 16, [135, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]],
[148, 160],
100),
{'layout': [[100, 148, [112]], [112, 160, []]], 'roots': [100, 112], 'top': 128}),
('interior root',
([[160, 16, []], [100, 16, [135, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [153], 100),
{'layout': [[100, 148, [112]], [112, 160, []]], 'roots': [105], 'top': 128}),
('compaction into a lower base',
([[160, 16, []], [100, 16, [135, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]],
[100, 148],
43),
{'layout': [[43, 100, [70, None]], [59, 124, [47]], [83, 148, [95]], [95, 160, []]],
'roots': [43, 83],
'top': 111}),
('control: no roots',
([[160, 16, []], [100, 16, [135, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [None], 100),
{'layout': [], 'roots': [None], 'top': 100})],
[('regression: interior pointers relocate with their object',
([[160, 16, []], [100, 16, [136, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [100], 100),
{'layout': [[100, 100, [128, None]], [116, 124, [104]]], 'roots': [100], 'top': 140}),
('dead objects do not advance the compaction pointer',
([[160, 16, []], [100, 16, [136, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [124], 100),
{'layout': [[100, 100, [128, None]], [116, 124, [104]]], 'roots': [116], 'top': 140}),
('pointer to an object start',
([[160, 16, []], [100, 16, [136, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]],
[148, 160],
100),
{'layout': [[100, 148, [112]], [112, 160, []]], 'roots': [100, 112], 'top': 128}),
('interior root',
([[160, 16, []], [100, 16, [136, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [150], 100),
{'layout': [[100, 148, [112]], [112, 160, []]], 'roots': [102], 'top': 128}),
('compaction into a lower base',
([[160, 16, []], [100, 16, [136, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]],
[100, 148],
44),
{'layout': [[44, 100, [72, None]], [60, 124, [48]], [84, 148, [96]], [96, 160, []]],
'roots': [44, 84],
'top': 112}),
('control: no roots',
([[160, 16, []], [100, 16, [136, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [None], 100),
{'layout': [], 'roots': [None], 'top': 100})],
[('regression: interior pointers relocate with their object',
([[160, 16, []], [100, 16, [137, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [100], 100),
{'layout': [[100, 100, [129, None]], [116, 124, [104]]], 'roots': [100], 'top': 140}),
('dead objects do not advance the compaction pointer',
([[160, 16, []], [100, 16, [137, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [124], 100),
{'layout': [[100, 100, [129, None]], [116, 124, [104]]], 'roots': [116], 'top': 140}),
('pointer to an object start',
([[160, 16, []], [100, 16, [137, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]],
[148, 160],
100),
{'layout': [[100, 148, [112]], [112, 160, []]], 'roots': [100, 112], 'top': 128}),
('interior root',
([[160, 16, []], [100, 16, [137, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [151], 100),
{'layout': [[100, 148, [112]], [112, 160, []]], 'roots': [103], 'top': 128}),
('compaction into a lower base',
([[160, 16, []], [100, 16, [137, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]],
[100, 148],
45),
{'layout': [[45, 100, [74, None]], [61, 124, [49]], [85, 148, [97]], [97, 160, []]],
'roots': [45, 85],
'top': 113}),
('control: no roots',
([[160, 16, []], [100, 16, [137, None]], [116, 8, []], [124, 24, [104]], [148, 12, [160]]], [None], 100),
{'layout': [], 'roots': [None], 'top': 100})]]
for label, args, expected in cases[N - 1]:
check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression: interior pointers relocate with their object | {'layout': [[100, 100, [125, None]], [116, 124, [104]]], 'roots': [100], 'top': 140} | {'layout': [[100, 100, [125, None]], [116, 124, [104]]], 'roots': [100], 'top': 140} | Passed |
| dead objects do not advance the compaction pointer | {'layout': [[100, 100, [125, None]], [116, 124, [104]]], 'roots': [116], 'top': 140} | {'layout': [[100, 100, [125, None]], [116, 124, [104]]], 'roots': [116], 'top': 140} | Passed |
| pointer to an object start | {'layout': [[100, 148, [112]], [112, 160, []]], 'roots': [100, 112], 'top': 128} | {'layout': [[100, 148, [112]], [112, 160, []]], 'roots': [100, 112], 'top': 128} | Passed |
| interior root | {'layout': [[100, 148, [112]], [112, 160, []]], 'roots': [103], 'top': 128} | {'layout': [[100, 148, [112]], [112, 160, []]], 'roots': [103], 'top': 128} | Passed |
| compaction into a lower base | {'layout': [[41, 100, [66, None]], [57, 124, [45]], [81, 148, [93]], [93, 160, []]], 'roots': [41, 81], 'top': 109} | {'layout': [[41, 100, [66, None]], [57, 124, [45]], [81, 148, [93]], [93, 160, []]], 'roots': [41, 81], 'top': 109} | Passed |
| control: no roots | {'layout': [], 'roots': [None], 'top': 100} | {'layout': [], 'roots': [None], 'top': 100} | Passed |
SHA-256 / 7f6661f7901952b2ebb5af39b303c2f4767975b75505b69b16e560bb03440d9c
Verification & scope
A deterministic, bounded teaching model of one garbage-collector mechanism with stipulated rules; it is not a production collector and claims no conformance to any particular runtime. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.
Observations recorded using Python 3.12.14 at 2026-09-29T14:51:26.820107+00:00.
Case digest / 51dd62e8e59e355e51f2dde8e2820ebb55f55f8cc2c67b3c366decc1a762ba54