align vm runtime

This commit is contained in:
bQUARKz 2026-02-20 06:11:13 +00:00
parent fa651af3c3
commit c7382763cd
Signed by: bquarkz
SSH Key Fingerprint: SHA256:Z7dgqoglWwoK6j6u4QC87OveEq74WOhFN+gitsxtkf8
4 changed files with 69 additions and 25 deletions

View File

@ -498,7 +498,7 @@ impl NativeInterface for VirtualMachineRuntime {
return Ok(());
}
Syscall::SystemRunCart => {
ret.push_null();
// ret_slots = 0 (void). Must return exactly 0 values per SyscallMeta.
return Ok(());
}
_ => {}
@ -513,15 +513,14 @@ impl NativeInterface for VirtualMachineRuntime {
// --- GFX Syscalls ---
// gfx.clear(color_index) -> null
// gfx.clear(color_index) -> void (ret_slots = 0)
Syscall::GfxClear => {
let color_val = expect_int(args, 0)?;
let color = self.get_color(color_val);
hw.gfx_mut().clear(color);
ret.push_null();
Ok(())
}
// gfx.draw_rect(x, y, w, h, color_index) -> null
// gfx.draw_rect(x, y, w, h, color_index) -> void (ret_slots = 0)
Syscall::GfxFillRect => {
let x = expect_int(args, 0)? as i32;
let y = expect_int(args, 1)? as i32;
@ -530,10 +529,9 @@ impl NativeInterface for VirtualMachineRuntime {
let color_val = expect_int(args, 4)?;
let color = self.get_color(color_val);
hw.gfx_mut().fill_rect(x, y, w, h, color);
ret.push_null();
Ok(())
}
// gfx.draw_line(x1, y1, x2, y2, color_index) -> null
// gfx.draw_line(x1, y1, x2, y2, color_index) -> void (ret_slots = 0)
Syscall::GfxDrawLine => {
let x1 = expect_int(args, 0)? as i32;
let y1 = expect_int(args, 1)? as i32;
@ -542,10 +540,9 @@ impl NativeInterface for VirtualMachineRuntime {
let color_val = expect_int(args, 4)?;
let color = self.get_color(color_val);
hw.gfx_mut().draw_line(x1, y1, x2, y2, color);
ret.push_null();
Ok(())
}
// gfx.draw_circle(x, y, r, color_index) -> null
// gfx.draw_circle(x, y, r, color_index) -> void (ret_slots = 0)
Syscall::GfxDrawCircle => {
let x = expect_int(args, 0)? as i32;
let y = expect_int(args, 1)? as i32;
@ -553,10 +550,9 @@ impl NativeInterface for VirtualMachineRuntime {
let color_val = expect_int(args, 3)?;
let color = self.get_color(color_val);
hw.gfx_mut().draw_circle(x, y, r, color);
ret.push_null();
Ok(())
}
// gfx.draw_disc(x, y, r, border_color_idx, fill_color_idx) -> null
// gfx.draw_disc(x, y, r, border_color_idx, fill_color_idx) -> void (ret_slots = 0)
Syscall::GfxDrawDisc => {
let x = expect_int(args, 0)? as i32;
let y = expect_int(args, 1)? as i32;
@ -566,10 +562,9 @@ impl NativeInterface for VirtualMachineRuntime {
let fill_color = self.get_color(fill_color_val);
let border_color = self.get_color(border_color_val);
hw.gfx_mut().draw_disc(x, y, r, border_color, fill_color);
ret.push_null();
Ok(())
}
// gfx.draw_square(x, y, w, h, border_color_idx, fill_color_idx) -> null
// gfx.draw_square(x, y, w, h, border_color_idx, fill_color_idx) -> void (ret_slots = 0)
Syscall::GfxDrawSquare => {
let x = expect_int(args, 0)? as i32;
let y = expect_int(args, 1)? as i32;
@ -580,7 +575,6 @@ impl NativeInterface for VirtualMachineRuntime {
let fill_color = self.get_color(fill_color_val);
let border_color = self.get_color(border_color_val);
hw.gfx_mut().draw_square(x, y, w, h, border_color, fill_color);
ret.push_null();
Ok(())
}
// gfx.set_sprite(asset_name, id, x, y, tile_id, palette_id, active, flip_x, flip_y, priority)
@ -617,7 +611,7 @@ impl NativeInterface for VirtualMachineRuntime {
priority,
};
}
ret.push_null();
// ret_slots = 0 (void). Must return exactly 0 values per SyscallMeta.
Ok(())
}
Syscall::GfxDrawText => {
@ -633,7 +627,7 @@ impl NativeInterface for VirtualMachineRuntime {
let color_val = expect_int(args, 3)?;
let color = self.get_color(color_val);
hw.gfx_mut().draw_text(x, y, &msg, color);
ret.push_null();
// ret_slots = 0 (void). Must return exactly 0 values per SyscallMeta.
Ok(())
}
// gfx.clear565(color_u16) -> void
@ -873,7 +867,7 @@ impl NativeInterface for VirtualMachineRuntime {
0,
prometeu_hal::LoopMode::Off,
);
ret.push_null();
// ret_slots = 0 (void). Must return exactly 0 values per SyscallMeta.
Ok(())
}
@ -909,7 +903,7 @@ impl NativeInterface for VirtualMachineRuntime {
hw.assets().find_slot_by_name(&asset_name, BankType::SOUNDS).unwrap_or(0);
hw.audio_mut().play(bank_id, sample_id, voice_id, volume, pan, pitch, 0, loop_mode);
ret.push_null();
// ret_slots = 0 (void). Must return exactly 0 values per SyscallMeta.
Ok(())
}
@ -971,7 +965,7 @@ impl NativeInterface for VirtualMachineRuntime {
Syscall::FsClose => {
let handle = expect_int(args, 0)? as u32;
self.open_files.remove(&handle);
ret.push_null();
// ret_slots = 0 (void). Must return exactly 0 values per SyscallMeta.
Ok(())
}
// FS_LIST_DIR(path)
@ -1087,13 +1081,13 @@ impl NativeInterface for VirtualMachineRuntime {
Syscall::AssetCommit => {
let handle = expect_int(args, 0)? as u32;
hw.assets().commit(handle);
ret.push_null();
// ret_slots = 0 (void). Must return exactly 0 values per SyscallMeta.
Ok(())
}
Syscall::AssetCancel => {
let handle = expect_int(args, 0)? as u32;
hw.assets().cancel(handle);
ret.push_null();
// ret_slots = 0 (void). Must return exactly 0 values per SyscallMeta.
Ok(())
}
Syscall::BankInfo => {

View File

@ -1732,11 +1732,17 @@ mod tests {
let mut ctx = HostContext::new(None);
vm.prepare_call("0");
vm.run_budget(100, &mut native, &mut ctx).unwrap();
assert_eq!(vm.pop().unwrap(), Value::Bounded(255));
assert_eq!(vm.pop().unwrap(), Value::Int64(42));
assert_eq!(vm.pop().unwrap(), Value::Boolean(true));
// Ensure we have SYSTEM capability so we pass capability gate
vm.set_capabilities(prometeu_hal::syscalls::caps::SYSTEM);
let report = vm.run_budget(100, &mut native, &mut ctx).unwrap();
// Under PR5, VM enforces return-slot count based on SyscallMeta during syscall
// execution. A mismatch yields a Panic with a descriptive message.
match report.reason {
LogicalFrameEndingReason::Panic(msg) => {
assert!(msg.contains("results mismatch"));
}
_ => panic!("Expected Panic with results mismatch, got {:?}", report.reason),
}
}
#[test]
@ -1810,6 +1816,8 @@ mod tests {
let mut ctx = HostContext::new(None);
vm.prepare_call("0");
// Ensure we have GFX capability so we reach type checking inside native handler
vm.set_capabilities(prometeu_hal::syscalls::caps::GFX);
let report = vm.run_budget(100, &mut native, &mut ctx).unwrap();
match report.reason {
@ -1832,6 +1840,8 @@ mod tests {
let mut ctx = HostContext::new(None);
vm.prepare_call("0");
// Grant GFX capability so arg underflow is checked (capability gate is first)
vm.set_capabilities(prometeu_hal::syscalls::caps::GFX);
let report = vm.run_budget(100, &mut native, &mut ctx).unwrap();
match report.reason {
@ -1857,6 +1867,8 @@ mod tests {
let mut ctx = HostContext::new(None);
vm.prepare_call("0");
// Grant GFX capability so arg underflow is checked (capability gate is first)
vm.set_capabilities(prometeu_hal::syscalls::caps::GFX);
let report = vm.run_budget(100, &mut native, &mut ctx).unwrap();
match report.reason {
@ -1949,6 +1961,8 @@ mod tests {
}
let mut vm = new_test_vm(rom.clone(), vec![]);
// Grant GFX capability so results mismatch path is exercised
vm.set_capabilities(prometeu_hal::syscalls::caps::GFX);
let mut native = BadNative;
let mut ctx = HostContext::new(None);

View File

@ -44,6 +44,8 @@ fn vm_syscall_multi_return_stack_contents() {
let mut native = TestNative;
let mut ctx = HostContext::new(None);
vm.prepare_call("0");
// Grant INPUT capability to pass capability gate for PadGetUp
vm.set_capabilities(prometeu_hal::syscalls::caps::INPUT);
let _ = vm.run_budget(100, &mut native, &mut ctx).expect("VM run failed");
// Verify stack order: last pushed is on top

34
files/VM RESET.md Normal file
View File

@ -0,0 +1,34 @@
6 — Closures (first-class user functions)
6.1. Definir objeto Closure no heap: fn_id + env (captures) + metadata mínima.
6.2. Definir como capturas são materializadas (layout do env e como o bytecode cria closures).
6.3. Implementar instruções/semântica para criar closure e para CALL_CLOSURE.
6.4. Atualizar GC traversal: closure → env → heap refs internos.
6.5. Atualizar verifier: tipo “closure value”, validação de call sites, ret_slots.
6.6. Testes: closure simples, closure capturando, closure retornando outra closure.
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.1. Consolidar documentação de arquitetura (curta, objetiva, em inglês).
9.2. Garantir que o “surface area” público está minimalista (APIs internas escondidas).
9.3. Remover qualquer feature flag temporária que tenha sobrado.
9.4. Rodar limpeza final: dead code, warnings, docs desatualizadas, exemplos antigos.