nmarshall commited on
Commit
142d4cb
·
1 Parent(s): 8a6d738

qvm: entity reuse policy

Browse files
docs/ASSET_PIPELINE_TODO.md CHANGED
@@ -493,3 +493,6 @@ Research progress: RE-602 [report](research/QVM_SERVER_FIRE_CHAIN.md); remaining
493
 
494
 
495
  Research progress: RE-604 [report](research/QVM_ENTITY_INIT.md); remaining native/content/runtime/platform scope stays open.
 
 
 
 
493
 
494
 
495
  Research progress: RE-604 [report](research/QVM_ENTITY_INIT.md); remaining native/content/runtime/platform scope stays open.
496
+
497
+
498
+ Research progress: RE-605 [report](research/QVM_ENTITY_REUSE.md); remaining native/content/runtime/platform scope stays open.
docs/FINDINGS.md CHANGED
@@ -851,3 +851,6 @@ Bounded qagame paths recover bomb-plant/inactivity correction requests, direct f
851
 
852
 
853
  **RE-604 — Entity initializer and preserved record fields:** 277125 writes only identity, in-use, noclass pointer/tag and owner sentinel; all other 215 words survive. [Evidence](research/QVM_ENTITY_INIT.md).
 
 
 
 
851
 
852
 
853
  **RE-604 — Entity initializer and preserved record fields:** 277125 writes only identity, in-use, noclass pointer/tag and owner sentinel; all other 215 words survive. [Evidence](research/QVM_ENTITY_INIT.md).
854
+
855
+
856
+ **RE-605 — Entity allocator reuse and recent-free guard:** The allocator scans from slot64, skips in-use records and delays recent frees only when freeTime>start+2000 and now−freeTime<1000. [Evidence](research/QVM_ENTITY_REUSE.md).
docs/PROVISIONAL_TODO.md CHANGED
@@ -813,3 +813,6 @@ Research progress: RE-602 [report](research/QVM_SERVER_FIRE_CHAIN.md); remaining
813
 
814
 
815
  Research progress: RE-604 [report](research/QVM_ENTITY_INIT.md); remaining native/content/runtime/platform scope stays open.
 
 
 
 
813
 
814
 
815
  Research progress: RE-604 [report](research/QVM_ENTITY_INIT.md); remaining native/content/runtime/platform scope stays open.
816
+
817
+
818
+ Research progress: RE-605 [report](research/QVM_ENTITY_REUSE.md); remaining native/content/runtime/platform scope stays open.
docs/RESEARCH_LEDGER.md CHANGED
@@ -707,3 +707,8 @@ RE-602 additional regression:19 related reports from RE-582–591 and RE-593–6
707
  ## 2026-10-20 — RE-604 Entity initializer and preserved record fields (separate task commit)
708
 
709
  277125 writes only identity, in-use, noclass pointer/tag and owner sentinel; all other 215 words survive. Independent full-record oracles cover 18 slot/canary combinations. Full suite: 922 tests pass. Report regenerates byte-identically (194019 bytes). Storage/filter, links and whitespace checks pass. No assets/Rust runtime/shared VM evaluator changed; native/reference/legal/full platform scope remains open.
 
 
 
 
 
 
707
  ## 2026-10-20 — RE-604 Entity initializer and preserved record fields (separate task commit)
708
 
709
  277125 writes only identity, in-use, noclass pointer/tag and owner sentinel; all other 215 words survive. Independent full-record oracles cover 18 slot/canary combinations. Full suite: 922 tests pass. Report regenerates byte-identically (194019 bytes). Storage/filter, links and whitespace checks pass. No assets/Rust runtime/shared VM evaluator changed; native/reference/legal/full platform scope remains open.
710
+
711
+
712
+ ## 2026-10-20 — RE-605 Entity allocator reuse and recent-free guard (separate task commit)
713
+
714
+ The allocator scans from slot64, skips in-use records and delays recent frees only when freeTime>start+2000 and now−freeTime<1000. Nineteen fixtures independently check first-fit order, strict timing boundaries, retained canaries and actual initializer calls. Full suite: 925 tests pass. Report regenerates byte-identically (574361 bytes). Storage/filter, links and whitespace checks pass. No assets/Rust runtime/shared VM evaluator changed; native/reference/legal/full platform scope remains open.
docs/REVERSE_ENGINEERING_TODO.md CHANGED
@@ -856,3 +856,6 @@ Purpose: turn the supplied installation into an evidence-backed specification of
856
 
857
 
858
  - [x] RE-604 Entity initializer and preserved record fields ([report](research/QVM_ENTITY_INIT.md)).
 
 
 
 
856
 
857
 
858
  - [x] RE-604 Entity initializer and preserved record fields ([report](research/QVM_ENTITY_INIT.md)).
859
+
860
+
861
+ - [x] RE-605 Entity allocator reuse and recent-free guard ([report](research/QVM_ENTITY_REUSE.md)).
docs/research/QVM_ENTITY_REUSE.md ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ # Entity allocator reuse and recent-free guard
2
+
3
+ RE-605. Reproduce with `python3 scripts/analyze_qvm_entity_reuse.py`; check with `python3 scripts/test_qvm_entity_reuse.py`. The [machine report](qvm-entity-reuse.json) retains source identity and bounded fixtures.
4
+
5
+ The actual first pass of277165 scans fixed pool34091368 in880-byte strides from slot64 to count34992508. A nonzero record532 always skips. On pass0 a free record is delayed only when record564>global34992544+2000 AND global34992532−record564<1000. Equality at either threshold permits reuse. Actual277125 initializes the selected record and the numeric pointer returns; count remains unchanged. The report stops at277262 if the scan exhausts its supplied small pool, leaving extension/retry policy for RE-606. Record contents are retained except the five initializer words; tests retain client-pointer canaries. The finite time fixtures avoid signed-overflow ambiguity; engine lifetime and clearing remain unresolved.
6
+
7
+ No original executable/full QVM/native collision/physics/rendering executes. Native responses and legal input domains are supplied or unverified where stated; full runtime/macOS/Linux Rust/Bevy/Solari gameplay remains open.
docs/research/README.md CHANGED
@@ -414,3 +414,6 @@ The extension collector adds five focused tests for native tail calls, command-r
414
 
415
 
416
  [RE-604: Entity initializer and preserved record fields](QVM_ENTITY_INIT.md). Reproduce with `python3 scripts/analyze_qvm_entity_init.py`; check with `python3 scripts/test_qvm_entity_init.py`.
 
 
 
 
414
 
415
 
416
  [RE-604: Entity initializer and preserved record fields](QVM_ENTITY_INIT.md). Reproduce with `python3 scripts/analyze_qvm_entity_init.py`; check with `python3 scripts/test_qvm_entity_init.py`.
417
+
418
+
419
+ [RE-605: Entity allocator reuse and recent-free guard](QVM_ENTITY_REUSE.md). Reproduce with `python3 scripts/analyze_qvm_entity_reuse.py`; check with `python3 scripts/test_qvm_entity_reuse.py`.
docs/research/qvm-entity-reuse.json ADDED
The diff for this file is too large to render. See raw diff
 
scripts/analyze_qvm_entity_reuse.py ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Actual first-pass allocator scan, stopping before extension/retry policy."""
3
+ import itertools
4
+ from pathlib import Path
5
+ from qvm_research_support import source,execute
6
+ from analyze_qvm_entity_init import initialize,POOL,STRIDE
7
+ from analyze_qvm_temp_event import record
8
+ from analyze_qvm import write_json
9
+ LOCAL=0x79100000
10
+
11
+ def fixture(count=66,now=5000,start=0,slots=()):
12
+ m={34992508:count,34992532:now,34992544:start,34992500:POOL,34992496:0x10000}
13
+ for index in range(64,max(count,65)):
14
+ p=POOL+index*STRIDE
15
+ for o in range(0,STRIDE,4):m[p+o]=0x12345678
16
+ m[p+532]=1;m[p+564]=0
17
+ for index,used,freed in slots:m[POOL+index*STRIDE+532]=used;m[POOL+index*STRIDE+564]=freed&0xffffffff
18
+ return m
19
+
20
+ def reuse(ins,m):
21
+ m=dict(m);initial={'count':m[34992508],'time':m[34992532],'start':m[34992544],'slots':[{'index':i,'used':m[POOL+i*STRIDE+532],'freed':m[POOL+i*STRIDE+564]} for i in range(64,m[34992508])]};children=[]
22
+ def init(i,m,a,c):m,r=initialize(i,m,a[8]);children.append(r);return m,c,0,r
23
+ m,_,r=execute(ins,277166,277262,m,(0,0,0),LOCAL,{277125:init})
24
+ return m,{'initial':initial,'execution':r,'selected':r['return'],'scan_index':m[LOCAL+32],'retry':m[LOCAL+36],'count':m[34992508],'record':record(m,r['return']) if r['return'] is not None else None,'initializers':children,'boundary':'returned' if r['return'] is not None else 'extension-or-retry-pending'}
25
+
26
+ def main():
27
+ q,raw,h,ins=source();rows=[]
28
+ for freed,now,start in itertools.product([0,2000,2001,4000,4001,4999,5000],[5000],[0,2500]):
29
+ rows.append(reuse(ins,fixture(slots=[(64,0,freed),(65,0,0)],now=now,start=start))[1])
30
+ for slots in [[],[(64,1,0),(65,0,0)],[(64,0,0),(65,0,0)],[(64,0,4999),(65,1,0)]]:rows.append(reuse(ins,fixture(slots=slots))[1])
31
+ rows.append(reuse(ins,fixture(count=64))[1])
32
+ write_json(Path('docs/research/qvm-entity-reuse.json'),{'source':q['source'],'sha256':q['sha256'],'probes':rows,'limits':'Actual277165 first pass with actual277125 child. No native effects. Stops277262 before count extension; full capacity retry is separate.'})
33
+ if __name__=='__main__':main()
scripts/test_qvm_entity_reuse.py ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json,unittest
2
+ from pathlib import Path
3
+ class EntityReuseTests(unittest.TestCase):
4
+ @classmethod
5
+ def setUpClass(cls):cls.r=json.loads(Path('docs/research/qvm-entity-reuse.json').read_text())
6
+ def test_independent_scan_policy(self):
7
+ for p in self.r['probes']:
8
+ a=p['initial'];eligible=[s['index'] for s in a['slots'] if s['used']==0 and (s['freed']<=a['start']+2000 or a['time']-s['freed']>=1000)];index=eligible[0] if eligible else a['count'];self.assertEqual(p['selected'],34091368+880*index if eligible else None);self.assertEqual(p['scan_index'],index);self.assertEqual(p['count'],a['count']);self.assertEqual(p['retry'],0)
9
+ def test_recent_free_strict_boundaries(self):
10
+ samples={ (p['initial']['slots'][0]['freed'],p['initial']['start']):p for p in self.r['probes'][:14] }
11
+ self.assertEqual(samples[(4000,0)]['scan_index'],64);self.assertEqual(samples[(4001,0)]['scan_index'],65);self.assertEqual(samples[(4001,2500)]['scan_index'],64)
12
+ def test_no_clear_and_actual_child(self):
13
+ for p in self.r['probes']:
14
+ self.assertEqual([c['target'] for c in p['execution']['calls']],[277125] if p['selected'] else [])
15
+ if p['record']:self.assertEqual(p['record']['520'],0x12345678);self.assertEqual(p['record']['532'],1)
16
+ if __name__=='__main__':unittest.main()