172 lines
4.7 KiB
Markdown
172 lines
4.7 KiB
Markdown
# Decision Record - VM-Owned Stateful Core Contract
|
|
|
|
## Status
|
|
|
|
Accepted
|
|
|
|
## Contexto
|
|
|
|
O runtime ja possui intrinsics VM-owned read-only (input), mas faltava um contrato canonico para recursos VM-owned stateful.
|
|
|
|
Sem esse contrato, cada dominio novo tende a divergir em:
|
|
|
|
- referencia/handle;
|
|
- lifecycle;
|
|
- shape de ABI por operacao;
|
|
- politica de fault/status;
|
|
- validacao de verifier/disasm.
|
|
|
|
## Decisao
|
|
|
|
### 1. Fronteira host-backed permanece inalterada
|
|
|
|
- `HOSTCALL`/`SYSCALL` continuam sendo o caminho host-backed.
|
|
- Esta decisao nao introduz redesign de host boundary.
|
|
|
|
### 2. Modelo canonico de recurso stateful
|
|
|
|
- Recurso stateful VM-owned e representado por `HeapRef<TBuiltinState>`.
|
|
- Validade da referencia segue `index + generation` (anti-stale).
|
|
- Nao sera introduzido, nesta etapa, um modelo paralelo de handle numerico tipado.
|
|
|
|
### 3. Lifecycle minimo obrigatorio
|
|
|
|
Todo dominio stateful deve explicitar:
|
|
|
|
- `create`;
|
|
- `read/query`;
|
|
- `update`;
|
|
- `destroy`.
|
|
|
|
### 4. Forma de invocacao
|
|
|
|
- O caminho de execucao permanece `INTRINSIC <id_final>`.
|
|
- Nao ha tabela adicional de pre-load para VM-owned stateful.
|
|
- IDs finais continuam versionados por operacao.
|
|
|
|
### 5. Metadata canonica por operacao intrinsic stateful
|
|
|
|
Cada operacao deve declarar, no minimo:
|
|
|
|
- `arg_slots`;
|
|
- `ret_slots`;
|
|
- `effect` (read/create/update/destroy);
|
|
- `determinism`;
|
|
- `may_allocate`;
|
|
- `cost_hint`.
|
|
|
|
### 6. Fault model para VM-owned stateful
|
|
|
|
- `Trap` para erro estrutural (shape de chamada invalido, stale handle, kind invalido).
|
|
- `status` para falha operacional de dominio.
|
|
- `Panic` apenas para inconsistencia interna do runtime.
|
|
|
|
### 7. GC/lifetime e aliasing
|
|
|
|
- Recursos stateful vivem na heap VM e seguem roots normais de GC.
|
|
- `destroy` existe para encerramento explicito quando o dominio exigir.
|
|
- Multipla referencia para o mesmo recurso nao muda semantica de ownership; validade segue regras de `HeapRef`.
|
|
|
|
### 8. Verifier/toolchain/disasm
|
|
|
|
- Verifier deve validar assinatura (`arg_slots`/`ret_slots`) e identidade da operacao.
|
|
- Disasm deve expor identidade canonica (nome + versao), nao apenas id numerico.
|
|
- Mudanca breaking exige nova versao da operacao.
|
|
|
|
### 9. Compatibilidade binaria
|
|
|
|
- Mesma versao de operacao nao muda contrato de slots nem efeito.
|
|
- Operacao inexistente/incompativel deve falhar em carga/verificacao.
|
|
|
|
## Estado Atual do Frontend PBS (Studio)
|
|
|
|
Estado observado:
|
|
|
|
- SDK interface ja modela VM-owned builtin surfaces com `declare builtin type` + `IntrinsicCall`.
|
|
- Lowering ja emite `CALL_INTRINSIC` e pipeline ja converte para opcode `INTRINSIC`.
|
|
|
|
Lacunas relevantes para stateful:
|
|
|
|
- resolucao de intrinsic no frontend ainda e indexada por `sourceMethodName` simples;
|
|
- ids de intrinsic no frontend ainda usam `hash(canonicalName#version)` como placeholder.
|
|
|
|
Direcao exigida por esta decisao:
|
|
|
|
- resolucao de intrinsic deve considerar identidade canonica sem ambiguidade de receiver;
|
|
- ids finais de intrinsic devem vir de registry canonico FE/backend/runtime, nao de hash provisoria.
|
|
|
|
## Exemplos (Ilustrativos, nao normativos)
|
|
|
|
### Exemplo A - Surface de SDK para random stateful na PBS
|
|
|
|
```text
|
|
[BuiltinType(name = "random", version = 1)]
|
|
declare builtin type Random() {
|
|
[IntrinsicCall(name = "new", version = 1)]
|
|
fn new(seed: int) -> RandomRng;
|
|
}
|
|
|
|
[BuiltinType(name = "random.rng", version = 1)]
|
|
declare builtin type RandomRng() {
|
|
[IntrinsicCall(name = "next", version = 1)]
|
|
fn next() -> int;
|
|
|
|
[IntrinsicCall(name = "destroy", version = 1)]
|
|
fn destroy() -> int; // status
|
|
}
|
|
|
|
[BuiltinConst(target = "random", name = "global", version = 1)]
|
|
declare const Random: Random;
|
|
```
|
|
|
|
### Exemplo B - Uso em userland PBS
|
|
|
|
```text
|
|
import { Random } from @sdk:random;
|
|
|
|
fn tick() -> void {
|
|
let rng = Random.new(12345);
|
|
let a = rng.next();
|
|
let b = rng.next();
|
|
let _s = rng.destroy();
|
|
}
|
|
```
|
|
|
|
### Exemplo C - Contraste de lowering
|
|
|
|
```text
|
|
CALL_INTRINSIC random.new@1
|
|
CALL_INTRINSIC random.rng.next@1
|
|
CALL_INTRINSIC random.rng.destroy@1
|
|
```
|
|
|
|
No bytecode final:
|
|
|
|
```text
|
|
INTRINSIC <id_random_new_v1>
|
|
INTRINSIC <id_random_rng_next_v1>
|
|
INTRINSIC <id_random_rng_destroy_v1>
|
|
```
|
|
|
|
## Consequencias
|
|
|
|
### Positivas
|
|
|
|
- cria base unica para dominios stateful VM-owned;
|
|
- evita proliferacao de protocolos ad hoc por servico;
|
|
- preserva fronteira host-backed atual;
|
|
- prepara random como primeiro consumidor sem redesenho posterior.
|
|
|
|
### Custos
|
|
|
|
- exige evolucao de registry/identity de intrinsic no frontend/backend;
|
|
- exige endurecimento de verifier/disasm para contrato stateful;
|
|
- exige disciplina de versionamento por operacao.
|
|
|
|
## Follow-up Obrigatorio
|
|
|
|
- agenda `011-vm-owned-stateful-core.md` deve ser considerada fechada por esta decisao;
|
|
- agenda `012-vm-owned-random-service.md` passa a ser o primeiro consumidor desta base;
|
|
- specs `16`/`16a` devem absorver o contrato stateful quando a implementacao ficar estavel.
|
|
|