From 5095fc1a76a488ed8059742d1cd1be4a96667ae1 Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Fri, 20 Feb 2026 07:07:33 +0000 Subject: [PATCH] pr6.4 --- crates/console/prometeu-vm/src/heap.rs | 66 ++++ files/TODOs.md | 413 ++++++++++++++++++++----- files/VM RESET.md | 21 +- 3 files changed, 406 insertions(+), 94 deletions(-) diff --git a/crates/console/prometeu-vm/src/heap.rs b/crates/console/prometeu-vm/src/heap.rs index fc3a01c3..f4d2b7fb 100644 --- a/crates/console/prometeu-vm/src/heap.rs +++ b/crates/console/prometeu-vm/src/heap.rs @@ -407,4 +407,70 @@ mod tests { assert!(!heap.is_valid(b)); assert_eq!(heap.len(), 0); } + + #[test] + fn gc_scans_closure_env_and_keeps_captured_heap_object() { + let mut heap = Heap::new(); + + // Captured heap object. + let obj = heap.allocate_object(ObjectKind::Bytes, &[4, 5, 6]); + + // Closure capturing the heap object among other primitive values. + let env = [Value::Boolean(true), Value::HeapRef(obj), Value::Int32(123)]; + let clo = heap.alloc_closure(1, &env); + + // Mark from closure root: both closure and captured object must be marked. + heap.mark_from_roots([clo]); + + assert!(heap.header(clo).unwrap().is_marked()); + assert!(heap.header(obj).unwrap().is_marked()); + + // Sweep should keep both and clear their marks. + heap.sweep(); + assert!(heap.is_valid(clo)); + assert!(heap.is_valid(obj)); + assert!(!heap.header(clo).unwrap().is_marked()); + assert!(!heap.header(obj).unwrap().is_marked()); + } + + #[test] + fn gc_scans_nested_closures_and_keeps_inner_when_outer_is_rooted() { + let mut heap = Heap::new(); + + // Inner closure (no env). + let inner = heap.alloc_closure(2, &[]); + + // Outer closure captures the inner closure as a Value::HeapRef. + let outer = heap.alloc_closure(3, &[Value::HeapRef(inner)]); + + // Root only the outer closure. + heap.mark_from_roots([outer]); + + // Both must be marked reachable. + assert!(heap.header(outer).unwrap().is_marked()); + assert!(heap.header(inner).unwrap().is_marked()); + + // After sweep, both survive and have marks cleared. + heap.sweep(); + assert!(heap.is_valid(outer)); + assert!(heap.is_valid(inner)); + assert!(!heap.header(outer).unwrap().is_marked()); + assert!(!heap.header(inner).unwrap().is_marked()); + } + + #[test] + fn gc_collects_unreferenced_closure_and_captures() { + let mut heap = Heap::new(); + + // Captured heap object and a closure capturing it. + let captured = heap.allocate_object(ObjectKind::String, b"dead"); + let clo = heap.alloc_closure(9, &[Value::HeapRef(captured)]); + + // No roots are provided; sweeping should reclaim both. + heap.sweep(); + + assert!(!heap.is_valid(clo)); + assert!(!heap.is_valid(captured)); + assert_eq!(heap.len(), 0); + } } diff --git a/files/TODOs.md b/files/TODOs.md index 9ebfcdc0..5f8ea7bd 100644 --- a/files/TODOs.md +++ b/files/TODOs.md @@ -1,76 +1,3 @@ -# PR-6.4 — GC Traversal for Closures (Model B) - -## Briefing - -Closures introduce heap-to-heap references through their captured environments. - -Under Model B, the closure object itself is passed at call time, but its environment remains stored in heap. - -GC must traverse: - -closure -> env -> inner HeapRefs - ---- - -## Target - -Extend GC mark phase to handle `ObjectKind::Closure`: - -When marking a closure: - -* Iterate over env values. -* If a value contains HeapRef → mark referenced object. - -No compaction. No relocation. - ---- - -## Work Items - -1. Extend mark traversal switch. -2. Ensure safe iteration over env payload. -3. Add regression tests. - ---- - -## Acceptance Checklist - -* [ ] Closure env scanned. -* [ ] Nested closures retained. -* [ ] No regression in existing GC tests. - ---- - -## Tests - -1. Closure capturing another closure. -2. Closure capturing heap object. -3. Unreferenced closure collected. - ---- - -## Junie Instructions - -You MAY: - -* Modify mark traversal. -* Add tests. - -You MUST NOT: - -* Modify sweep policy. -* Introduce compaction. - -If unsure whether Value variants can embed HeapRef, STOP and ask. - ---- - -## Definition of Done - -GC correctly traverses closure environments under Model B semantics. - ---- - # PR-6.5 — Verifier Support for Closures (Model B) ## Briefing @@ -147,4 +74,342 @@ If function metadata (arg_slots/ret_slots) is insufficient, STOP and request cla ## Definition of Done -Verifier fully supports closure creation and invocation under Model B semantics. \ No newline at end of file +Verifier fully supports closure creation and invocation under Model B semantics. + +--- + +# PR-7 — Coroutines (Cooperative, Deterministic, No Mailbox) + +Coroutines are the **only concurrency model** in the Prometeu VM. + +This phase introduces: + +* Cooperative scheduling +* Deterministic execution order +* SPAWN / YIELD / SLEEP +* Switching only at safepoints (FRAME_SYNC) +* Full GC integration + +No mailbox. No message passing. No preemption. + +Each PR below is self-contained and must compile independently. + +--- + +# PR-7.1 — Coroutine Heap Object + +## Briefing + +A coroutine is a suspended execution context with its own stack and call frames. + +No mailbox is implemented in this phase. + +## Target + +Define `ObjectKind::Coroutine` with: + +* `state: enum { Ready, Running, Sleeping, Finished, Faulted }` +* `wake_tick: u64` +* `stack: Vec` +* `frames: Vec` + +Rules: + +* Allocated in GC heap. +* Addressed via `HeapRef`. +* Stack and frames stored inside the coroutine object. + +## Checklist + +* [ ] Coroutine heap object defined. +* [ ] Stack/frames encapsulated. +* [ ] No RC/HIP remnants. +* [ ] Compiles and tests pass. + +## Tests + +* Allocate coroutine object. +* Validate state transitions manually. + +## Junie Rules + +You MAY extend heap object kinds. +You MUST NOT implement scheduling yet. +If stack representation is unclear, STOP and ask. + +--- + +# PR-7.2 — Deterministic Scheduler Core + +## Briefing + +Implement a cooperative deterministic scheduler. + +## Target + +Scheduler structure inside VM: + +* `ready_queue: VecDeque` +* `sleeping: Vec` (sorted or scanned by wake_tick) +* `current: Option` + +Policy: + +* FIFO for ready coroutines. +* Sleeping coroutines move to ready when `wake_tick <= current_tick`. + +No execution switching yet. + +## Checklist + +* [ ] Scheduler struct exists. +* [ ] Deterministic FIFO behavior. +* [ ] No randomness. + +## Tests + +* Enqueue 3 coroutines and ensure dequeue order stable. + +## Junie Rules + +You MAY add scheduler struct. +You MUST NOT implement SPAWN/YIELD/SLEEP yet. + +--- + +# PR-7.3 — SPAWN Instruction + +## Briefing + +SPAWN creates a new coroutine and schedules it. + +## Target + +Introduce opcode: + +`SPAWN fn_id, arg_count` + +Semantics: + +* Pop `arg_count` args. +* Create new coroutine object. +* Initialize its stack/frame with entry fn. +* Push coroutine handle onto ready queue. + +Current coroutine continues execution. + +## Checklist + +* [ ] SPAWN opcode exists. +* [ ] Coroutine created. +* [ ] Scheduled in ready queue. +* [ ] No immediate context switch. + +## Tests + +* Spawn coroutine and verify it appears in ready queue. + +## Junie Rules + +You MAY modify interpreter dispatch. +You MUST NOT switch execution immediately. +If entry frame layout unclear, STOP and ask. + +--- + +# PR-7.4 — YIELD Instruction + +## Briefing + +YIELD voluntarily gives up execution. + +## Target + +Opcode: + +`YIELD` + +Semantics: + +* Current coroutine moves to end of ready queue. +* Scheduler selects next coroutine at safepoint. + +Switching must occur only at FRAME_SYNC. + +## Checklist + +* [ ] YIELD opcode implemented. +* [ ] Current coroutine enqueued. +* [ ] No mid-instruction switching. + +## Tests + +* Two coroutines yielding alternate deterministically. + +## Junie Rules + +You MAY modify VM execution loop. +You MUST NOT allow switching outside safepoints. + +--- + +# PR-7.5 — SLEEP Instruction + +## Briefing + +SLEEP suspends coroutine until a future tick. + +## Target + +Opcode: + +`SLEEP duration_ticks` + +Semantics: + +* Remove coroutine from ready queue. +* Set wake_tick. +* Add to sleeping list. + +At each FRAME_SYNC: + +* Check sleeping coroutines. +* Move ready ones to ready_queue. + +## Checklist + +* [ ] SLEEP implemented. +* [ ] wake_tick respected. +* [ ] Deterministic wake behavior. + +## Tests + +* Sleep and verify delayed execution. + +## Junie Rules + +You MAY add tick tracking. +You MUST NOT rely on real wall clock time. + +--- + +# PR-7.6 — Safepoint Integration + +## Briefing + +Execution switching must occur only at safepoints. + +## Target + +Switch coroutine only: + +* After FRAME_SYNC +* After instruction completes + +Never mid-instruction. + +## Checklist + +* [ ] Switch only at safepoints. +* [ ] No reentrancy. + +## Tests + +* Stress test switching under heavy loops. + +## Junie Rules + +You MUST enforce deterministic switching. + +--- + +# PR-7.7 — GC Integration + +## Briefing + +Suspended coroutines must be GC roots. + +## Target + +GC mark phase must traverse: + +* All coroutine stacks +* All coroutine frames + +## Checklist + +* [ ] GC visits all suspended coroutines. +* [ ] No leaked references. + +## Tests + +* Coroutine capturing heap object remains alive. +* Finished coroutine collected. + +## Junie Rules + +You MUST NOT change sweep policy. + +--- + +# PR-7.8 — Verifier Rules + +## Briefing + +Verifier must enforce coroutine safety. + +## Target + +Rules: + +* YIELD forbidden inside invalid contexts (define minimal safe rule). +* SPAWN argument validation. +* SLEEP argument type validation. + +## Checklist + +* [ ] Invalid YIELD rejected. +* [ ] SPAWN arg mismatch rejected. + +## Tests + +* Invalid bytecode rejected. + +## Junie Rules + +You MUST NOT weaken verifier. + +--- + +# PR-7.9 — Determinism & Stress Tests + +## Briefing + +Validate deterministic behavior. + +## Target + +Tests must confirm: + +* Same order across runs. +* Sleep/wake order stable. +* GC works with many coroutines. + +## Checklist + +* [ ] Deterministic order tests. +* [ ] Stress test 100+ coroutines. + +## Junie Rules + +Tests must not depend on wall clock or randomness. + +--- + +## Final Definition of Done + +* Cooperative coroutines implemented. +* Deterministic scheduling. +* No mailbox. +* GC and verifier fully integrated. +* All tests pass. diff --git a/files/VM RESET.md b/files/VM RESET.md index 44468a61..e2254978 100644 --- a/files/VM RESET.md +++ b/files/VM RESET.md @@ -1,23 +1,4 @@ -vamos as PR7s todas em um unico canvas markdown ingles, devem ser auto contidas com briefing, alvo, checklist, test quando necessario e comandos do que a Junie pode ou nao fazer (Junie eh task operator nao arquiteta ou assume nada, questiona quando necessario). - -7 — Coroutines (único modelo de concorrência, cooperativo) - -7.1. Definir objeto Coroutine no heap: stack/frames próprios, status, wake time, mailbox/queue se existir. -7.2. Definir scheduler determinístico: fila pronta, fila dormindo, política estável. -7.3. Implementar SPAWN: criar coroutine + capturar entry + agendar. -7.4. Implementar YIELD: ceder controle de forma cooperativa (somente em locais válidos). -7.5. Implementar SLEEP: mover para fila dormindo até tick/time. -7.6. Integrar execução/switch apenas em safepoints (FRAME_SYNC). -7.7. Integrar GC roots: stacks suspensas e frames de todas as coroutines. -7.8. Verifier: invariantes (ex.: proibir yield em contextos ilegais, validar spawn args/ret). -7.9. Testes: determinismo (mesma ordem), sleep/wake, stress com GC + muitas coroutines. - -8 — Tooling & test harness (para manter “JVM-grade”) - -8.1. Disasm atualizado e confiável (roundtrip + snapshots). -8.2. Harness de execução determinística para testes (seed fixo, time controlado). -8.3. Suite de testes por camadas: bytecode (encode/decode), verifier, VM, GC, scheduler. -8.4. “No legacy artifacts” check: busca por símbolos/nomes (retain/release/hip/gate/scope), módulos mortos removidos. +vamos as PR9s todas em um unico canvas markdown ingles, devem ser auto contidas com briefing, alvo, checklist, test quando necessario e comandos do que a Junie pode ou nao fazer (Junie eh task operator nao arquiteta ou assume nada, questiona quando necessario). 9 — Hardening final e documentação do novo baseline