VM Value, Call, and Runtime Contracts
Goal
Choose a safe, efficient VM-internal value/call model and extract only the genuinely backend-neutral runtime contracts. Keep native ABI adaptation at the native boundary.
- Nine of the eleven contracts this section names have zero definitions in the tree:
VmCallSig,RuntimeCallSpec,VmLayoutPlan,CompiledLayoutPlan,ReprEvidence,EnumReprEvidence,VmEnumLayout,CompiledEnumLayout,TargetSpec. Onlyori_llvm::codegen::abi::FunctionAbi(abi/mod.rs:107) andori_repr::executable::ExecutableProgram(executable/mod.rs:189) resolve. - This is a coinage section whose vocabulary is owned upstream, not a refactor of existing contracts. Its first act is to CONSUME the sibling name freeze, never to author a competing spelling.
- The measured deliverable is the value/call model and the runtime-contract read-view. The safety and dependency-direction clauses (
unsafe_code = "deny", noori_llvm/oricdependency) are already true and are preserve-invariants, not budget.
Ownership Boundaries — what this section may not author
- Name freeze:
VmLayoutPlan/CompiledLayoutPlan(TargetSpec)carry 28 plan references acrossbytecode-vm,repr-opt#13,enum-layout-ssot,clang-arc-lessons,ffi-boundary-safety, anditerator-element-ownership, and zero code definitions.bytecode-vm#s-429b48feholds the freeze and states every remaining item is blocked on it. Coining a competing spelling here isLEAK:scattered-knowledgeacross eight plans. - Built-in callable identity:
RuntimeCall::from_symbol(runtime.rs:258) matches raw string spellings and collapses"ori_panic" | "ori_panic_cstr"into onePanicidentity, thougharc.md §Protocol Builtinsgives them opposite ownership contracts (ori_panicconsumesmsgas an RL-2 transfer;ori_panic_cstrborrows). That cure isbytecode-vm#s-374b9321(DESIGN-30,hr-3f982596bd15b2c4). This section consumes the corrected identity; it never extends the string table. - Enum layout:
EnumTag::payload_gep_index()(enum_repr.rs:126) is an LLVM-aggregate-index accessor already living in the sharedori_reprcrate — D4’s prohibition has a live counterexample. It is owned by the IN-PROGRESSenum-layout-ssot#s-0f9158abover the sameVmLayoutPlan/ExecutableProgram/EnumLayoutInfosurface. Coordinate; do not edit. - Compiled ABI:
FunctionAbi,compute_function_abi_with_ownership,select_call_conv, andcompute_closure_param_passingare owned by the IN-PROGRESSBUG-05-007#05plusnative-backend#s-35021a4c/repr-opt#12/#13. They are the section’s constrained symbols;select_call_convandcompute_closure_param_passingare exactly the target calling-convention and byval/indirect selection D2 bans fromVmCallSig. - Fourth-computer hazard: BUG-05-009 already names three parallel store-size/layout computers (
ori_arc::pool_type_store_size,ori_llvm::type_store_size,ori_repr::compute_field_layout) and prescribes one shared repr-owned kernel. AVmLayoutPlanauthored here either discharges that thesis or becomes its fourth instance.
The Incumbent This Section Must Argue Against
ori_vm::execute::value::VmValue(value.rs:32) is{ tag: ValueTag, payload: u64 }with a static 16-byte assertion, over a 21-variant#[repr(u8)] ValueTag(11 of themIteratorStep*mirrors of the other 10 — a product encoded as a sum). That is a dynamic tag on every slot: the exact opposite of D1’s rule that the opcode supplies the static type.- The shape is byte-for-byte Lua 5.4 (
lobject.h:49/:67, 16 B) while the plan’s memory north star is pinned LuaJIT-joff, whoseTValue(lj_obj.h:174) is an 8-byte NaN-boxed union. The 2x per-slot disadvantage is baked in before the section starts, and mission gate 6 makes memory unconditional. PhysicalFunctionPlan/PhysicalLane/PhysicalPcPlan/OperandSpan(physical/layout.rs:10-165) already ARE an unnamedVmLayoutPlan, exported asPhysicalVmPlan. TheVmLayoutPlandeliverable is largely rename-and-freeze, not greenfield.runtime_argument_ownership(ori_vm/src/execute/runtime.rs:47) already threadsori_arc::ArgOwnershipper call-site operand. D5’s per-argument-ownership gap is on the DESCRIPTOR, not the call site.
Implementation Sketch
- Prototype at least two safe representations against representative opcodes and calls: typed register banks/lanes, and fixed-size aligned slots with side metadata. The opcode supplies the static type; a dynamic tag is introduced only at a genuine dynamic boundary.
- Define “genuine dynamic boundary” operationally rather than by intuition: a CFG merge whose predecessors disagree on the AIMS ownership obligation for a slot. Prove or refute that
KnownFacts::intersect_with(ori_vm/src/physical/facts.rs:81) keeps a lane-keyed ownership map precise across such merges. Where it cannot, the fallback is a hybrid — untagged lanes for merge-invariant obligations, a narrow tagged lane only at the merges that fail the test, never universally. - Prior art constrains the option set rather than supplying it: WasmKit ships untyped uniform slots with types recovered statically from the instruction stream, and its frame decomposition (header / locals / constant pool / dynamic stack) is a frame vocabulary that names no
sret, no calling convention, and no target stack rules. wasm3’s op-chaining mechanism is the indirect-table shape this plan already measured at 1.676x slower than a match loop on stable Rust and rejected. NaN-boxing and pointer-tagging literature answers a dynamic-typing constraint Ori does not share. No fetched source removed the tag while preserving a per-slot ownership obligation; that remainder is this section’s actual design work. - Derive a logical
VmCallSigfrom canonical types, backend-neutralReprEvidence, and typed AIMS carriers. It describes VM arguments, results, references, and ownership effects; it does not import compiled calling conventions,sret, Fast/CCC, target stack rules, or LLVM attributes. - Keep
VmCallSigseparate from compiledFunctionAbi. Perrepr-opt#13andnative-backend#s-35021a4c, one backend-neutral compiled ABI classifier is consumed by LLVM andori_backend; the VM does not become a third consumer of platform ABI frames. The crate graph already forecloses the import (ori_vmdepends only onori_arc,ori_ir,ori_registry,ori_repr), so the live risk is shape mimicry —VmCallSigre-deriving indirect/byval/sretreasoning insideori_vm— which is reviewer-time semantic, not a dependency lint. Express the split as two sibling descriptors over one logical source, mirroring lua’sCallInfoversus luajit’s separateCCallInfo; never as one type with a mode flag, and never as an overlay stacked on the platform ABI. - Keep
VmCallSigto one type.abi::CallConv ~ abi::CallConvSiteis the highest-similarity duplication pair in the scoped set (0.954); a VM “calling convention” enum plus a VM “call site” enum reproduces that twin insideori_vm. - Per
plans/enum-layout-ssot, deriveVmEnumLayoutfrom shared enum evidence and VM policy. VM tag/payload locations, safe handles, and trace/drop schemas never reuseCompiledEnumLayoutbyte offsets or LLVM aggregate indices. The genuinely neutral evidence ismin_tag_width/VariantRepr/is_pointer;payload_gep_indexis not, and is constrained. - Extract a backend-neutral
RuntimeCallSpeccontaining identity, semantic signature, per-argument ownership, result independence/aliasing, unwind contract, and capability requirements.RuntimeCalltoday carries exactly one semantic fact (arity()); five of D5’s six facets are absent. LLVM declarations andori_backendruntime calls translate the spec through the shared compiled layout/ABI plan; VM calls translate it to safe runtime wrappers. - Extract
RuntimeCallSpecas a DERIVED READ-VIEW overExecutableProgram’s existingparameter_facts,return_facts,effect_facts,drop_plan, andparam_disjointnessfamilies, not as newExecutableProgramPartsfields. The 19 highest-churn symbols inori_vmare hand-builtExecutableProgramtest fixtures (the first production symbol ranks 20th at a 13x lower score); every new field on the shared contract is paid for 19 times in fixture construction before a production line changes. Those*_factsaccessors also already form a 0.82-0.88 similarity mesh, so a fifth member multiplies the duplication signal as well as the fixture tax. - Preserve the layer’s uniform shape: every scoped identity type in
ori_repr::executablederivesCopy + Hash + structural Eqwith zero#[allow], zero suppression, zerocfg. ARuntimeCallSpeccarrying aVec<ArgOwnership>breaksCopyand departs from that convention — use a fixed-arity array or an interned index. Do not spray(ownership, aliasing, unwind, capabilities)as four parallel side tables keyed byRuntimeCall. - Never derive the ownership facet from a collapsed identity: an ownership field computed for the merged
ori_panic | ori_panic_cstridentity is provably wrong for one of the two. - Keep source semantics separate from backend storage optimization. A call declared to borrow and return independent storage may not mutate or return an unretained alias merely because dynamic RC is one: RC uniqueness does not prove that the source value is dead. A future consume-and-COW fast path must be an explicit proved ownership-transfer variant selected from shared AIMS/liveness facts, with a reference borrowed variant and evaluator/VM/LLVM parity pins.
- Make the safety clause structural rather than merely forbidden: the ownership authority for a slot is the frozen AIMS fact at that program point, carried in a side map keyed by
(lane, pc-range), never a dynamic RC observation read out of the slot. QuickJS’sJS_DupValue/JS_FreeValuegate ownership work on the tag; removing the tag removes that gate, so ownership actions must resolve statically from the opcode plus the frozen plan. - Keep the first VM crate
unsafe_code = "deny". WorkspaceCargo.toml:107already denies it,ori_vminherits via[lints] workspace = true, andori_vm/srccontains zerounsafe. Raw native-bit-compatible storage requires a measured win, an explicit safety design, and project approval; mixed-tier frames and OSR remain out of scope.
Spec & Rules
ReprEvidencesupplies neutral extent/range/niche/field facts;VmLayoutPlanchooses VM storage, whileCompiledLayoutPlanchooses the one target layout/ABI shared by LLVM andori_backend. None is currently a deterministic Salsa key or serialized chunk format, and none currently exists as a definition — the names are consumed frombytecode-vm#s-429b48fe’s freeze.- Enum evidence follows the same split:
EnumReprEvidenceis shared,VmEnumLayoutis interpreter-private, andCompiledEnumLayoutis the single target-specific input to both compiled backends. - Runtime call descriptors are semantic contracts. LLVM values/attributes remain in
ori_llvm; BIR/MIR/emission objects remain inori_backend. - Runtime implementation choices must satisfy the descriptor’s aliasing and ownership contract in every profile. Dynamic uniqueness can select a representation strategy only inside the authority granted by that contract.
- VM execution preserves the exact post-AIMS logical ownership-event, cleanup,
transfer, COW/reuse, and unwind identities. Its validated
VmLayoutPlanmay realize them with counters, tracing, regions, copying, recycling, or an individually proved no-op; it never imports the compiled projection’sRc*instruction spelling or reclassifies policy. - Calculus-first per
arc.md §CP-1: if the lane-keyed ownership map requires a new AIMS ownership-transfer variant, the governing theorem is proven in the compiled Lean corpus BEFORE any Rust is written, with scratch Lean (§CP-4) used to test the CFG-merge case first.arc.mdPV-2 clauses (2)/(3) — running count >= 1 at every READ and >= 1 + live siblings at every MUTATE — are the obligations a conservative merge must not silently trade for a keep-alive leak or a reintroduced dynamic check. - Ground the ownership facet in the burden-sole survivor stream before designing it: run
ori build <file>.ori --emit-rc-remarks/compiler_repo/diagnostics/rc-stats.sh --rc-remarksand read thecause.lattice_dimhistogram, which names the boundaries where an under-specified VM descriptor produces a leak or a double-free. A DEFAULT-path RC count is FALSE-GREEN and is never a verdict (arc.md §STOP);codegen-audit.shandarc-dump.shsupply the compiled-ABI and post-AIMS carrier views, andbisect-passes.sh --rc-onlycarries no VM verdict at all.
Layer Coverage
| Layer | Disposition |
|---|---|
| L1 | N/A: no grammar changes. |
| L2 | N/A: no typechecking semantics change. |
| L3 | N/A: no canonicalization semantics change. |
| L4 | Covered by the neutral representation/AIMS ownership contract criterion; a new ownership-transfer variant additionally requires its compiled-Lean theorem per arc.md §CP-1. |
| L5 | N/A: the representations are contract/prototype inputs; production execution begins in the skeleton. This N/A is CONDITIONAL — it holds only while the section ships zero production-path execution change; the first such change converts L5 to covered. |
| L6 | Covered by the LLVM-debug runtime-descriptor regression criterion. |
| L7 | Covered by the LLVM-release runtime-descriptor regression criterion. |
| L8 | Covered by the AOT runtime-descriptor regression criterion. |
| L9 | Covered by the section cross-executor criterion. The comparator is currently red on BUG-04-283 (critical), BUG-04-234, BUG-04-188, and BUG-04-272 — shapes these contracts must cover. A green reading obtained from a corpus that dodges them is INVERTED-TDD:goal-drift; BUG-04-188 (owned list temporary passed to a borrowing builtin not dropped under --backend=llvm) is the compiled-side instance of D5’s own per-argument-ownership defect class. |
| L10 | Covered by the section leak-freedom criterion. |
| L11 | Covered by the ABI/runtime contract-fixture criterion. No graph-visible spec anchor reaches these files (spec-diagnostics: substrate-dark); source the clauses directly from compiler_repo/docs/ori_lang/v2026/spec/. |
| L12 | N/A: this internal contract has no independent user entry point. |
- Coverage claims are established by a real run, never from the intel graph’s test topology:
test-posturereportsdirect_tests: 0forori_llvm::codegen::abi::tests, a test module that exists on disk. The facet is inverted, not merely stale. history-coupling(co-change) andsurprise-couplingare DARK for this file set, so the “what will this contract change drag in” surface is unavailable from the graph. Blast-radius claims are confirmed at source;callers compute_function_abiis itselfpartialwith three unresolved occurrences.
Work Items
- Prototype and select a safe typed VM slot model plus logical
VmCallSigfrom shared AIMS and representation facts, explicitly arguing against the incumbentori_vm::execute::value::VmValue(21-variantValueTag+u64payload, 16 bytes/slot) toward the pinned LuaJIT-joffTValue(8 bytes) as the measured target for mission gate 6; consume theVmLayoutPlan/CompiledLayoutPlan(TargetSpec)name freeze frombytecode-vm#s-429b48ferather than coining an independent name. Define D1’s ‘genuine dynamic boundary’ operationally as a CFG merge whose predecessors disagree on the AIMS ownership obligation for a slot, and prove or refute thatKnownFacts::intersect_with(ori_vm/src/physical/facts.rs:81) keeps a lane-keyed ownership map precise across such merges; where it cannot, use a narrow tagged lane only at the merges that fail this test (not universally) as the hybrid fallback. Keep the shared compiledFunctionAbiout of VM frames, and document the deferred raw-layout/OSR decision. If the prototype requires a new AIMS ownership-transfer variant, prove the governing rule in the compiled Lean corpus (arc.md §CP-1) before implementing it, using scratch Lean (§CP-4) to test the merge case first. - Record
VmEnumLayout’s boundary against the sharedori_repr::enum_reprevidence (EnumRepr,min_tag_width,VariantRepr) and explicitly excludepayload_gep_index(an LLVM-aggregate-index accessor that has escaped into the shared crate, doc-commented as GEP index for the payload in the LLVM struct) from any VM-side derivation. Coordinate directly with the in-progressenum-layout-ssot#s-0f9158abplan, which ownsEnumLayoutInfoover the sameVmLayoutPlan/ExecutableProgramsurface; do not authorVmEnumLayoutindependently while that plan is in-progress — land the coordination decision (adopt its coinage, or explicitly defer VmEnumLayout authoring past its completion) instead of an independent enum-layout contract. - Extract backend-neutral
RuntimeCallSpecas a derived read-view overExecutableProgram’s existingparameter_facts,return_facts,effect_facts,drop_plan, andparam_disjointnessfamilies — not as newExecutableProgramPartsfields — covering identity, semantic signature, per-argument ownership, result independence/aliasing, unwind contract, and capability requirements, while preservingCopy + Hash + Eqshape (a fixed-arity array or interned index for the ownership facet, never aVec). Do not fix theori_panic/ori_panic_cstrfrom_symbolidentity collapse or extend the string-literal identity table — that cure belongs tobytecode-vm#s-374b9321(DESIGN-30,hr-3f982596bd15b2c4); this section consumes its corrected identity once landed. Do not touchpayload_gep_index(owned by in-progressenum-layout-ssot#s-0f9158ab),FunctionAbi/compute_function_abi_with_ownership(owned by in-progressBUG-05-007#05/native-backend#s-35021a4c/repr-opt#12/#13), orselect_call_conv/compute_closure_param_passing(target calling-convention selection D2 forbids inVmCallSig). Build safe VM wrappers over the extracted spec whileori_llvm-specific declarations andori_backendBIR/emitter details stay in their owning crates; prove evaluator/VM/LLVM debug/release/AOT behavior unchanged.
Intel dossier — pointer and tier disposition
Dossier: value-abi-runtime-alignment--s-f9b40534.intel.md (this section’s content/intel/ sidecar)
Read that dossier from line 1 through EOF before acting on this section. This block is a pointer and an audit record, never a substitute: not the BLUF, not a summary, not selected tiers.
| Dossier tier | Title | Lines | Disposition | Where / why |
|---|---|---|---|---|
| 0 | 0. Bottom line up front | 25 | integrated | ## Goal; ## Ownership Boundaries — what this section may not author; ## The Incumbent This Section Must Argue Against |
| 1 | 1. The target, verbatim | 30 | integrated | ## Goal (target sentence preserved verbatim); ## Implementation Sketch (D1-D6 restated against live-tree status); ## Layer Coverage (L5 N/A made explicitly CONDITIONAL on shipping zero production-path execution change) |
| 2 | 2. Terrain — what actually exists | 75 | integrated | ## The Incumbent This Section Must Argue Against (VmValue/ValueTag 16B, PhysicalFunctionPlan as unnamed VmLayoutPlan, runtime_argument_ownership); ## Ownership Boundaries (RuntimeCall::from_symbol collapse, payload_gep_index, compiled-ABI classifier); ## Implementation Sketch (RuntimeCall carries only arity(); neutral enum evidence is min_tag_width/VariantRepr/is_pointer) |
| 3 | 3. Code-graph recon | 132 | integrated | ## Implementation Sketch (crate graph forecloses the ori_llvm import so the live D3 risk is shape mimicry; RuntimeCallSpec as a derived read-view against the 19-fixture churn tax; Copy + Hash + structural Eq shape constraint from the uniform attribute posture); ## Layer Coverage (trailing bullets: test-topology facet inverted so coverage needs a real run; co-change and surprise-coupling dark; callers compute_function_abi partial) |
| 3D | 3D. Diagnostic / observability surface | 23 | integrated | ## Spec & Rules (final bullet: ground the ownership facet in the burden-sole —emit-rc-remarks / rc-stats.sh cause.lattice_dim histogram before designing it; DEFAULT-path RC counts are FALSE-GREEN per arc.md §STOP; codegen-audit.sh / arc-dump.sh roles; bisect-passes.sh carries no VM verdict) |
| 3H | 3H. Hygiene constraints the recommended design must satisfy | 25 | integrated | ## Ownership Boundaries (coining a competing spelling is LEAK:scattered-knowledge; BUG-05-009 fourth-computer hazard); ## Implementation Sketch (never derive the ownership facet from the collapsed ori_panic/ori_panic_cstr identity; no non-Copy spec and no four parallel side tables); ## Spec & Rules (arc.md §CP-1 calculus-first before any new ownership-transfer variant); ## Layer Coverage L9 (INVERTED-TDD:goal-drift on a corpus that dodges the red shapes) |
| 4 | 4. The cluster — related bugs | 25 | integrated | ## Ownership Boundaries — the fourth-computer-hazard bullet naming BUG-05-009 as the root-cause sibling this deliverable either discharges or joins; ## Layer Coverage L9 — the comparator recorded red on BUG-04-283, BUG-04-234, BUG-04-188 and BUG-04-272, with BUG-04-188 named as the compiled-side instance of D5’s own per-argument-ownership defect class |
| 5 | 5. Conformance audit — parallel-drift / MISSING_ABSTRACTION | 29 | integrated | ## Implementation Sketch (keep VmCallSig to one type — the CallConv ~ CallConvSite 0.954 twin must not be reproduced inside ori_vm; the ExecutableProgram *_facts accessors already form a 0.82-0.88 similarity mesh, so RuntimeCallSpec is a derived read-view rather than a fifth member) |
| 6 | 6. Plan ownership — who owns this vocabulary | 34 | integrated | ## Goal (coinage section whose vocabulary is owned upstream; first act is to consume a freeze); ## Ownership Boundaries (name freeze at bytecode-vm#s-429b48fe with the 28-reference/0-definition ratio; identity cure at s-374b9321; enum layout at in-progress enum-layout-ssot#s-0f9158ab; compiled ABI at in-progress BUG-05-007#05 / native-backend#s-35021a4c / repr-opt#12/#13) |
| 7 | 7. Prior art — in-graph | 38 | integrated | ## The Incumbent This Section Must Argue Against (Ori’s VmValue is byte-for-byte the Lua 5.4 16-byte shape against a LuaJIT lj_obj.h:174 8-byte TValue north star; the 21-variant tag is a product encoded as a sum); ## Implementation Sketch (express the VmCallSig / FunctionAbi split as two sibling descriptors mirroring lua CallInfo vs luajit CCallInfo, never one type with a mode flag; removing the tag removes QuickJS’s tag-gated ownership hook, so ownership must resolve statically from the opcode plus the frozen plan) |
| 7W | 7W. External prior art (web) — open-hard target | 75 | integrated | ## Implementation Sketch (the operational definition of ‘genuine dynamic boundary’ as a CFG merge whose predecessors disagree on the AIMS obligation, plus the KnownFacts::intersect_with probe and the narrow-hybrid fallback; the prior-art bullet: WasmKit untagged static-typed slots and its header/locals/constant-pool/dynamic-stack frame vocabulary, wasm3’s op-chaining already measured at 1.676x and rejected, NaN-boxing answering a dynamic-typing constraint Ori does not share, and the unmapped ownership remainder as the section’s real design work; the (lane, pc-range)-keyed side map making the safety clause structural rather than merely forbidden) |
| 8 | 8. Sentiment — unavailable, declared | 13 | not_applicable | The tier’s own finding is that the sentiment surface is absent, not weak: lua/luajit/quickjs/mruby/wasm3 are code-indexed but issue-dark, so pain/controversy percentiles cannot be computed and the tier explicitly neither raises nor lowers the test bar. Its declared substitutes are already carried elsewhere — the measured external tradeoffs by tier 7W and the plan’s own recorded probes by the Implementation Sketch. It imposes no constraint of its own on what this section must say; the absence itself is recorded by tier 9’s declared-gap list. |
| 9 | 9. Declared coverage gaps | 31 | integrated | ## Layer Coverage (trailing bullets: the inverted test-topology facet means coverage claims come from a real run, and the dark co-change / surprise-coupling surfaces plus the partial ABI caller inventory force source confirmation for blast radius) and L11 (spec-diagnostics substrate-dark, so clauses are sourced directly from compiler_repo/docs/ori_lang/v2026/spec/); ## Ownership Boundaries (the constrained-symbols set payload_gep_index / FunctionAbi / compute_function_abi_with_ownership / select_call_conv / compute_closure_param_passing recorded as external hazards, not deliverables) |
| 10 | 10. Recommended recon entry points | 25 | not_applicable | This tier is a navigation reading list for whoever executes the section, not a constraint on what the section’s own headings must say. Every entry on it lands in the body through the tier that supplies its substance — s-429b48fe and s-374b9321 via tier 6, value.rs / physical/layout.rs / runtime.rs / enum_repr.rs / executable/mod.rs via tier 2, facts.rs:81 via tier 7W, BUG-05-009 via tier 4, and arc.md §Protocol Builtins / §CP-1 via tiers 3H and 7W. It changed no heading beyond what those tiers already changed, and recording it as integrated would double-count them. |