This commit is contained in:
bQUARKz 2026-02-20 07:07:33 +00:00
parent 29736e9577
commit 5095fc1a76
Signed by: bquarkz
SSH Key Fingerprint: SHA256:Z7dgqoglWwoK6j6u4QC87OveEq74WOhFN+gitsxtkf8
3 changed files with 406 additions and 94 deletions

View File

@ -407,4 +407,70 @@ mod tests {
assert!(!heap.is_valid(b)); assert!(!heap.is_valid(b));
assert_eq!(heap.len(), 0); 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);
}
} }

View File

@ -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) # PR-6.5 — Verifier Support for Closures (Model B)
## Briefing ## Briefing
@ -147,4 +74,342 @@ If function metadata (arg_slots/ret_slots) is insufficient, STOP and request cla
## Definition of Done ## Definition of Done
Verifier fully supports closure creation and invocation under Model B semantics. 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<Value>`
* `frames: Vec<CallFrame>`
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<HeapRef>`
* `sleeping: Vec<HeapRef>` (sorted or scanned by wake_tick)
* `current: Option<HeapRef>`
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.

View File

@ -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). 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).
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.
9 — Hardening final e documentação do novo baseline 9 — Hardening final e documentação do novo baseline