This commit is contained in:
bQUARKz 2026-02-18 15:13:37 +00:00
parent d929f68dd7
commit 6d875784ea
Signed by: bquarkz
SSH Key Fingerprint: SHA256:Z7dgqoglWwoK6j6u4QC87OveEq74WOhFN+gitsxtkf8
3 changed files with 69 additions and 37 deletions

View File

@ -11,6 +11,8 @@ pub struct OpcodeSpec {
pub is_branch: bool, // has a control-flow target
pub is_terminator: bool, // ends basic block: JMP/RET/TRAP/HALT
pub may_trap: bool, // runtime trap possible
/// Marks this opcode as a VM safepoint. Used by GC/scheduler policies.
pub is_safepoint: bool,
}
pub trait OpCodeSpecExt {
@ -28,6 +30,7 @@ impl OpCodeSpecExt for OpCode {
is_branch: false,
is_terminator: false,
may_trap: false,
is_safepoint: false,
},
OpCode::Halt => OpcodeSpec {
name: "HALT",
@ -37,6 +40,7 @@ impl OpCodeSpecExt for OpCode {
is_branch: false,
is_terminator: true,
may_trap: false,
is_safepoint: false,
},
OpCode::Jmp => OpcodeSpec {
name: "JMP",
@ -46,6 +50,7 @@ impl OpCodeSpecExt for OpCode {
is_branch: true,
is_terminator: true,
may_trap: false,
is_safepoint: false,
},
OpCode::JmpIfFalse => OpcodeSpec {
name: "JMP_IF_FALSE",
@ -55,6 +60,7 @@ impl OpCodeSpecExt for OpCode {
is_branch: true,
is_terminator: false,
may_trap: true,
is_safepoint: false,
},
OpCode::JmpIfTrue => OpcodeSpec {
name: "JMP_IF_TRUE",
@ -64,6 +70,7 @@ impl OpCodeSpecExt for OpCode {
is_branch: true,
is_terminator: false,
may_trap: true,
is_safepoint: false,
},
OpCode::Trap => OpcodeSpec {
name: "TRAP",
@ -73,6 +80,7 @@ impl OpCodeSpecExt for OpCode {
is_branch: false,
is_terminator: true,
may_trap: true,
is_safepoint: false,
},
OpCode::PushConst => OpcodeSpec {
name: "PUSH_CONST",
@ -82,6 +90,7 @@ impl OpCodeSpecExt for OpCode {
is_branch: false,
is_terminator: false,
may_trap: false,
is_safepoint: false,
},
OpCode::Pop => OpcodeSpec {
name: "POP",
@ -91,6 +100,7 @@ impl OpCodeSpecExt for OpCode {
is_branch: false,
is_terminator: false,
may_trap: false,
is_safepoint: false,
},
OpCode::PopN => OpcodeSpec {
name: "POP_N",
@ -100,6 +110,7 @@ impl OpCodeSpecExt for OpCode {
is_branch: false,
is_terminator: false,
may_trap: false,
is_safepoint: false,
},
OpCode::Dup => OpcodeSpec {
name: "DUP",
@ -109,6 +120,7 @@ impl OpCodeSpecExt for OpCode {
is_branch: false,
is_terminator: false,
may_trap: false,
is_safepoint: false,
},
OpCode::Swap => OpcodeSpec {
name: "SWAP",
@ -118,6 +130,7 @@ impl OpCodeSpecExt for OpCode {
is_branch: false,
is_terminator: false,
may_trap: false,
is_safepoint: false,
},
OpCode::PushI64 => OpcodeSpec {
name: "PUSH_I64",
@ -127,6 +140,7 @@ impl OpCodeSpecExt for OpCode {
is_branch: false,
is_terminator: false,
may_trap: false,
is_safepoint: false,
},
OpCode::PushF64 => OpcodeSpec {
name: "PUSH_F64",
@ -136,6 +150,7 @@ impl OpCodeSpecExt for OpCode {
is_branch: false,
is_terminator: false,
may_trap: false,
is_safepoint: false,
},
OpCode::PushBool => OpcodeSpec {
name: "PUSH_BOOL",
@ -145,6 +160,7 @@ impl OpCodeSpecExt for OpCode {
is_branch: false,
is_terminator: false,
may_trap: false,
is_safepoint: false,
},
OpCode::PushI32 => OpcodeSpec {
name: "PUSH_I32",
@ -154,6 +170,7 @@ impl OpCodeSpecExt for OpCode {
is_branch: false,
is_terminator: false,
may_trap: false,
is_safepoint: false,
},
OpCode::PushBounded => OpcodeSpec {
name: "PUSH_BOUNDED",
@ -163,6 +180,7 @@ impl OpCodeSpecExt for OpCode {
is_branch: false,
is_terminator: false,
may_trap: true,
is_safepoint: false,
},
OpCode::Add => OpcodeSpec {
name: "ADD",
@ -172,6 +190,7 @@ impl OpCodeSpecExt for OpCode {
is_branch: false,
is_terminator: false,
may_trap: true,
is_safepoint: false,
},
OpCode::Sub => OpcodeSpec {
name: "SUB",
@ -181,6 +200,7 @@ impl OpCodeSpecExt for OpCode {
is_branch: false,
is_terminator: false,
may_trap: true,
is_safepoint: false,
},
OpCode::Mul => OpcodeSpec {
name: "MUL",
@ -190,6 +210,7 @@ impl OpCodeSpecExt for OpCode {
is_branch: false,
is_terminator: false,
may_trap: true,
is_safepoint: false,
},
OpCode::Div => OpcodeSpec {
name: "DIV",
@ -199,6 +220,7 @@ impl OpCodeSpecExt for OpCode {
is_branch: false,
is_terminator: false,
may_trap: true,
is_safepoint: false,
},
OpCode::Mod => OpcodeSpec {
name: "MOD",
@ -208,6 +230,7 @@ impl OpCodeSpecExt for OpCode {
is_branch: false,
is_terminator: false,
may_trap: true,
is_safepoint: false,
},
OpCode::BoundToInt => OpcodeSpec {
name: "BOUND_TO_INT",
@ -217,6 +240,7 @@ impl OpCodeSpecExt for OpCode {
is_branch: false,
is_terminator: false,
may_trap: false,
is_safepoint: false,
},
OpCode::IntToBoundChecked => OpcodeSpec {
name: "INT_TO_BOUND_CHECKED",
@ -226,6 +250,7 @@ impl OpCodeSpecExt for OpCode {
is_branch: false,
is_terminator: false,
may_trap: true,
is_safepoint: false,
},
OpCode::Eq => OpcodeSpec {
name: "EQ",
@ -235,6 +260,7 @@ impl OpCodeSpecExt for OpCode {
is_branch: false,
is_terminator: false,
may_trap: false,
is_safepoint: false,
},
OpCode::Neq => OpcodeSpec {
name: "NEQ",
@ -244,6 +270,7 @@ impl OpCodeSpecExt for OpCode {
is_branch: false,
is_terminator: false,
may_trap: false,
is_safepoint: false,
},
OpCode::Lt => OpcodeSpec {
name: "LT",
@ -253,6 +280,7 @@ impl OpCodeSpecExt for OpCode {
is_branch: false,
is_terminator: false,
may_trap: false,
is_safepoint: false,
},
OpCode::Gt => OpcodeSpec {
name: "GT",
@ -262,6 +290,7 @@ impl OpCodeSpecExt for OpCode {
is_branch: false,
is_terminator: false,
may_trap: false,
is_safepoint: false,
},
OpCode::And => OpcodeSpec {
name: "AND",
@ -271,6 +300,7 @@ impl OpCodeSpecExt for OpCode {
is_branch: false,
is_terminator: false,
may_trap: false,
is_safepoint: false,
},
OpCode::Or => OpcodeSpec {
name: "OR",
@ -280,6 +310,7 @@ impl OpCodeSpecExt for OpCode {
is_branch: false,
is_terminator: false,
may_trap: false,
is_safepoint: false,
},
OpCode::Not => OpcodeSpec {
name: "NOT",
@ -289,6 +320,7 @@ impl OpCodeSpecExt for OpCode {
is_branch: false,
is_terminator: false,
may_trap: false,
is_safepoint: false,
},
OpCode::BitAnd => OpcodeSpec {
name: "BIT_AND",
@ -298,6 +330,7 @@ impl OpCodeSpecExt for OpCode {
is_branch: false,
is_terminator: false,
may_trap: false,
is_safepoint: false,
},
OpCode::BitOr => OpcodeSpec {
name: "BIT_OR",
@ -307,6 +340,7 @@ impl OpCodeSpecExt for OpCode {
is_branch: false,
is_terminator: false,
may_trap: false,
is_safepoint: false,
},
OpCode::BitXor => OpcodeSpec {
name: "BIT_XOR",
@ -316,6 +350,7 @@ impl OpCodeSpecExt for OpCode {
is_branch: false,
is_terminator: false,
may_trap: false,
is_safepoint: false,
},
OpCode::Shl => OpcodeSpec {
name: "SHL",
@ -325,6 +360,7 @@ impl OpCodeSpecExt for OpCode {
is_branch: false,
is_terminator: false,
may_trap: false,
is_safepoint: false,
},
OpCode::Shr => OpcodeSpec {
name: "SHR",
@ -334,6 +370,7 @@ impl OpCodeSpecExt for OpCode {
is_branch: false,
is_terminator: false,
may_trap: false,
is_safepoint: false,
},
OpCode::Lte => OpcodeSpec {
name: "LTE",
@ -343,6 +380,7 @@ impl OpCodeSpecExt for OpCode {
is_branch: false,
is_terminator: false,
may_trap: false,
is_safepoint: false,
},
OpCode::Gte => OpcodeSpec {
name: "GTE",
@ -352,6 +390,7 @@ impl OpCodeSpecExt for OpCode {
is_branch: false,
is_terminator: false,
may_trap: false,
is_safepoint: false,
},
OpCode::Neg => OpcodeSpec {
name: "NEG",
@ -361,6 +400,7 @@ impl OpCodeSpecExt for OpCode {
is_branch: false,
is_terminator: false,
may_trap: false,
is_safepoint: false,
},
OpCode::GetGlobal => OpcodeSpec {
name: "GET_GLOBAL",
@ -370,6 +410,7 @@ impl OpCodeSpecExt for OpCode {
is_branch: false,
is_terminator: false,
may_trap: false,
is_safepoint: false,
},
OpCode::SetGlobal => OpcodeSpec {
name: "SET_GLOBAL",
@ -379,6 +420,7 @@ impl OpCodeSpecExt for OpCode {
is_branch: false,
is_terminator: false,
may_trap: false,
is_safepoint: false,
},
OpCode::GetLocal => OpcodeSpec {
name: "GET_LOCAL",
@ -388,6 +430,7 @@ impl OpCodeSpecExt for OpCode {
is_branch: false,
is_terminator: false,
may_trap: false,
is_safepoint: false,
},
OpCode::SetLocal => OpcodeSpec {
name: "SET_LOCAL",
@ -397,6 +440,7 @@ impl OpCodeSpecExt for OpCode {
is_branch: false,
is_terminator: false,
may_trap: false,
is_safepoint: false,
},
OpCode::Call => OpcodeSpec {
name: "CALL",
@ -406,6 +450,7 @@ impl OpCodeSpecExt for OpCode {
is_branch: false,
is_terminator: false,
may_trap: true,
is_safepoint: false,
},
OpCode::Ret => OpcodeSpec {
name: "RET",
@ -415,6 +460,7 @@ impl OpCodeSpecExt for OpCode {
is_branch: false,
is_terminator: true,
may_trap: false,
is_safepoint: false,
},
OpCode::PushScope => OpcodeSpec {
name: "PUSH_SCOPE",
@ -424,6 +470,7 @@ impl OpCodeSpecExt for OpCode {
is_branch: false,
is_terminator: false,
may_trap: false,
is_safepoint: false,
},
OpCode::PopScope => OpcodeSpec {
name: "POP_SCOPE",
@ -433,6 +480,7 @@ impl OpCodeSpecExt for OpCode {
is_branch: false,
is_terminator: false,
may_trap: false,
is_safepoint: false,
},
OpCode::Syscall => OpcodeSpec {
name: "SYSCALL",
@ -442,6 +490,7 @@ impl OpCodeSpecExt for OpCode {
is_branch: false,
is_terminator: false,
may_trap: true,
is_safepoint: false,
},
OpCode::FrameSync => OpcodeSpec {
name: "FRAME_SYNC",
@ -451,6 +500,7 @@ impl OpCodeSpecExt for OpCode {
is_branch: false,
is_terminator: false,
may_trap: false,
is_safepoint: true,
},
}
}

View File

@ -73,3 +73,22 @@ For exact immediates and stack effects, see `CoreOpCode::spec()` which is the si
- `CoreOpCode` — the opcode enum of the core profile.
- `CoreOpcodeSpec` and `CoreOpCodeSpecExt` — spec with `imm_bytes`, stack effects, and flags.
- Consumers (encoder/decoder/disasm/verifier) should import from this module to avoid depending on internal layout.
#### FRAME_SYNC — Semantics and Placement (Bytecode Level)
- Semantics:
- `FRAME_SYNC` is a zero-operand instruction and does not modify the operand stack.
- It marks a VM safepoint for GC and the cooperative scheduler. In `CoreOpcodeSpec` this is exposed as `spec.is_safepoint == true`.
- On execution, the VM may suspend the current fiber/coroutine until the next frame boundary (e.g., vsync) and/or perform GC. After resuming, execution continues at the next instruction.
- Placement rules (representable and checkable):
- `FRAME_SYNC` may appear anywhere inside a function body where normal instructions can appear. It is NOT a block terminator (`spec.is_terminator == false`).
- Instruction boundaries are canonical: encoders/emitters must only place `FRAME_SYNC` at valid instruction PCs. The verifier already enforces “jump-to-boundary” and end-exclusive `[start, end)` function ranges using the canonical layout routine.
- Entrypoints that represent a render/update loop SHOULD ensure at least one reachable `FRAME_SYNC` along every long-running path to provide deterministic safepoints for GC/scheduling. This policy is semantic and may be enforced by higher-level tooling; at the bytecode level it is representable via `spec.is_safepoint` and can be counted by static analyzers.
- Disassembly:
- Disassemblers must print the mnemonic `FRAME_SYNC` verbatim for this opcode.
- Tools MAY optionally annotate it as a safepoint in comments, e.g., `FRAME_SYNC ; safepoint`.
- Verification notes:
- The bytecode verifier treats `FRAME_SYNC` as a normal instruction with no stack effect and no control-flow targets. It is permitted before `RET`, between basic blocks, and as the last instruction of a function. Jumps targeting the function end (`pc == end`) remain valid under the end-exclusive rule.

View File

@ -1,40 +1,3 @@
# PR-1.6 — Canonical Function Boundaries & `FRAME_SYNC` Placement (Bytecode Layout)
### Briefing
GC and coroutine scheduling rely on deterministic safepoints. The bytecode layout must define canonical function boundaries and `FRAME_SYNC` semantics at the bytecode layer.
### Target
* Enforce canonical function ranges and end labels.
* Ensure `FRAME_SYNC` placement rules are representable and checkable.
### Work items
* Review current layout utilities and make them canonical for:
* Computing function `code_len`.
* Determining valid jump targets (instruction boundaries).
* Determining function end boundary.
* Document `FRAME_SYNC` at the bytecode level:
* What it signals.
* Where it is required (as per updated specs).
* Update disasm to clearly display `FRAME_SYNC`.
### Acceptance checklist
* [ ] Function boundaries are computed via a single canonical routine.
* [ ] `FRAME_SYNC` is clearly represented and documented.
* [ ] Existing verifier/layout tests (if any) are updated.
* [ ] `cargo test` passes.
### Tests
* Add or update unit tests for layout boundary correctness (e.g., end-exclusive semantics).
---
# PR-1.7 — Bytecode Roundtrip Tests (Encode/Decode/Disasm Sanity)
### Briefing