pub struct BytecodeProgram {Show 33 fields
pub instructions: Vec<Instruction>,
pub constants: Vec<Constant>,
pub strings: Vec<String>,
pub functions: Vec<Function>,
pub debug_info: DebugInfo,
pub data_schema: Option<DataFrameSchema>,
pub module_binding_names: Vec<String>,
pub top_level_locals_count: u16,
pub top_level_local_storage_hints: Vec<StorageHint>,
pub module_binding_storage_hints: Vec<StorageHint>,
pub function_local_storage_hints: Vec<Vec<StorageHint>>,
pub top_level_frame: Option<FrameDescriptor>,
pub top_level_local_concrete_types: Vec<ConcreteType>,
pub function_local_concrete_types: Vec<Vec<ConcreteType>>,
pub function_return_concrete_types: Vec<ConcreteType>,
pub monomorphized_method_call_sites: HashMap<(Span, Option<usize>), usize>,
pub value_call_return_concrete_types: HashMap<(Span, Option<usize>), ConcreteType>,
pub operator_trait_dispatch_sites: HashMap<Span, (String, u16)>,
pub type_schema_registry: TypeSchemaRegistry,
pub compiled_annotations: HashMap<String, CompiledAnnotation>,
pub trait_method_symbols: HashMap<String, String>,
pub expanded_function_defs: HashMap<String, FunctionDef>,
pub string_index: HashMap<String, u32>,
pub foreign_functions: Vec<ForeignFunctionEntry>,
pub native_struct_layouts: Vec<NativeStructLayoutEntry>,
pub top_level_mir: Option<Arc<MirFunctionData>>,
pub content_addressed: Option<Program>,
pub function_blob_hashes: Vec<Option<FunctionHash>>,
pub monomorphization_keys: Vec<String>,
pub closure_function_layouts: Vec<Option<Arc<ClosureLayout>>>,
pub trait_vtables: HashMap<String, Arc<VTable>>,
pub has_imported_const_inline: bool,
pub has_w17_marshal_residual: bool,
}Expand description
A compiled bytecode program
Fields§
§instructions: Vec<Instruction>The bytecode instructions
constants: Vec<Constant>Constant pool for literals
strings: Vec<String>String pool for identifiers and properties
functions: Vec<Function>Function table
debug_info: DebugInfoDebug information (always present, used for error messages)
data_schema: Option<DataFrameSchema>DataFrame schema for column name resolution (required for data access)
module_binding_names: Vec<String>ModuleBinding variable names (index -> name mapping for REPL persistence)
top_level_locals_count: u16Number of locals used by top-level code.
The executor advances sp past this many slots before execution
so that expression evaluation doesn’t overlap with local storage.
top_level_local_storage_hints: Vec<StorageHint>Storage hints for top-level locals (index -> hint). Used by JIT lowering to preserve native width integer codegen.
module_binding_storage_hints: Vec<StorageHint>Storage hints for module bindings (index -> hint).
function_local_storage_hints: Vec<Vec<StorageHint>>Per-function local storage hints.
function_local_storage_hints[f][local] is the hint for local slot in function f.
top_level_frame: Option<FrameDescriptor>Typed frame layout for top-level locals.
When present, supersedes top_level_local_storage_hints for the
JIT and VM. None means fall back to the legacy hints vec.
top_level_local_concrete_types: Vec<ConcreteType>Per-slot fully-resolved ConcreteType for top-level locals.
ADR-006 §2.7.5 conduit: stamped at bytecode-compile time from the
compiler’s proven type information (the typed-array kind chosen by
compile_expr_array, schema name from the type-tracker for struct
slots, etc.). The JIT MirToIR reads this side-table to drive the
v2 typed-array fast path (Rvalue::Aggregate short-circuit) and
the TypedObject ObjectStore short-circuit.
ConcreteType::Void per slot means “no information available” —
downstream consumers fall back to the legacy NaN-boxed path. This
is NOT a Bool-default fallback per §2.7.5.1 / forbidden #9; Void
is the explicit “no concrete type” sentinel value in the
ConcreteType enum, distinct from a fabricated scalar kind.
Not serialized — ConcreteType carries opaque StructLayoutId /
EnumLayoutId IDs that index into compile-time registries; the
cached-program path rebuilds them from the program’s other
metadata or falls through to the legacy path.
function_local_concrete_types: Vec<Vec<ConcreteType>>Per-user-function per-MIR-slot ConcreteType side-table.
function_local_concrete_types[f][slot] is the proven
ConcreteType for MIR slot slot in function index f. Empty
inner vec when the function has no MIR data or the conduit
couldn’t prove anything for the slot.
Producer: infer_top_level_concrete_types_from_mir (name is
historical — its body is generic over any MIR function) called
per Function::mir_data in
compiler_impl_reference_model::compile_post_assembly.
Consumer: compile_function_with_user_funcs at
crates/shape-jit/src/compiler/program.rs, which threads the
per-function entry into MirToIR::concrete_types.
ADR-006 §2.7.5 — W12-jit-aggregate-non-array close, 2026-05-12.
Same NOT-serialized rationale as top_level_local_concrete_types.
function_return_concrete_types: Vec<ConcreteType>Per-user-function declared ConcreteType for the function’s return value.
function_return_concrete_types[f] is the ConcreteType derived
from FunctionDef.return_type via
compiler::v2_map_emission::concrete_type_from_annotation. Used
by the conduit producer
(infer_top_level_concrete_types_from_mir) to stamp Call-
terminator destination slots: when the caller writes
let r = divide(10, 2), the r slot’s ConcreteType is the
callee’s return type (here, Result(I64, String)).
ConcreteType::Void per entry means “no annotation” or
“annotation didn’t reduce to a known shape” — the conduit and
JIT consumers treat Void as the no-information sentinel per
§2.7.5.1. NOT a Bool-default fallback per forbidden #9.
Producer: compile_post_assembly — per-function walk after the
per-function MIR conduit populate.
Consumer: infer_top_level_concrete_types_from_mir extended
with the callee-return resolver parameter.
ADR-006 §2.7.5 — W12-jit-call-return-kind close, 2026-05-12.
Same NOT-serialized rationale as the sibling *_concrete_types
side-tables; ConcreteType isn’t wire-stable.
monomorphized_method_call_sites: HashMap<(Span, Option<usize>), usize>ADR-006 §2.7.5 conduit — per-call-site monomorphized-method FunctionId side-table (V3-S6b-jit-method-monomorph-conduit close, 2026-05-15; supervisor 2026-05-15 PATH α RATIFIED).
Populated at bytecode-compile time by
try_monomorphize_method_call /
try_monomorphize_method_call_with_closures on specialization
success: the AST Expr::MethodCall.span together with the
currently-compiling caller function index keys the specialized
FunctionId of the callee. The composite (Span, calling_function)
key disambiguates specialization-within-generic-function cases
where the same source-level Span gets monomorphized multiple
times under different caller specialization contexts.
Consumed at the conduit producer
(infer_top_level_concrete_types_from_mir_with_resolvers’s
MirConstant::Method Call-terminator pass) — when the side-table
has an entry for (terminator.span, current_function), the
destination slot’s ConcreteType is lifted from
function_return_concrete_types[specialized_idx] (i.e. the
callee specialization’s declared return type). This carries the
.map() chain’s intermediate carrier shape through to the JIT-
side parametric_method_return_kind_from_receiver arm at
crates/shape-jit/src/mir_compiler/types.rs:946, which then
trivially classifies .sum() after .map() on Vec<I64> →
Int64 via the existing
("sum"|"mean"|..., ConcreteType::Array(elem)) arm.
PATH α per supervisor 2026-05-15 ratification (side-table on BytecodeProgram + Program + LinkedProgram; PATH β MIR back-patching is FALLBACK ONLY; PATH γ runtime conduit-extension REFUSED per V3-S6a sub-agent SIGSEGV finding — carrier-shape mismatch soundness violation).
#[serde(skip, default)] per the same wire-format rationale as
function_return_concrete_types — opaque FunctionId indices into
the per-program function table aren’t a stable wire shape.
value_call_return_concrete_types: HashMap<(Span, Option<usize>), ConcreteType>ADR-006 §2.7.5 conduit — per-call-site value-call return
ConcreteType side-table (cluster-2-cw-IB-class-b close,
2026-05-16; supervisor R3 binding-ratified).
Populated at bytecode-compile time by
compile_expr_function_call’s value-call branch
(crates/shape-vm/src/compiler/expressions/function_calls.rs:498-619)
when the callee resolves to a local closure binding whose body’s
return ConcreteType is recoverable via caller-context inference
(i.e. caller-supplied typed-array args reveal the closure’s
otherwise-inferred typed-array param). The composite key
(call-site Span, calling_function) mirrors the
monomorphized_method_call_sites shape so identical Spans inside
different specialization contexts can carry distinct entries.
Consumed at the conduit producer
(infer_top_level_concrete_types_from_mir_with_resolvers’s
value-call Call-terminator pass) — when the side-table has an
entry for (terminator.span, current_function) AND the
terminator’s func operand reads from a local slot (the
closure-bound slot), the destination slot’s ConcreteType is
stamped from the side-table value. The downstream JIT consumer’s
place_native_kind projection then picks up the destination’s
NativeKind, and the print Call-terminator’s kinded dispatch
at terminators.rs:447-744 reaches its matching scalar arm
(e.g. Some(NativeKind::Int64) => print_i64).
Class B coverage per inventory §B.2: closure body with INFERRED
typed-array param (the let f = |inner| inner.sum(); print(f(xs))
fixture). Pre-fix: VM=15 / JIT=NotImplemented(SURFACE,
print operand NativeKind=None). Post-fix: VM=15 / JIT=15.
#[serde(skip, default)] per the same wire-format rationale as
function_return_concrete_types — ConcreteType carries opaque
per-program registry IDs that aren’t a stable wire shape.
operator_trait_dispatch_sites: HashMap<Span, (String, u16)>ADR-006 §2.7.5 conduit — per-binop-or-unop-site operator trait dispatch side-table (W10 jit-call-method-user-trait-fix close, 2026-05-17).
Populated at bytecode-compile time by
compile_expr_binary_op / compile_expr_unary_op whenever the
bytecode emits an OpCode::CallMethod for user-type operator
overloading (the trait-dispatch branches in
crates/shape-vm/src/compiler/expressions/binary_ops.rs:1469-1474,
binary_ops.rs::try_emit_trait_dispatch, and
crates/shape-vm/src/compiler/expressions/unary_ops.rs:89-103
(Neg) / :189-203 (Not)). Keyed by the AST Span of the
Expr::BinaryOp / Expr::UnaryOp node — the same span the MIR
lowering at crates/shape-vm/src/mir/lowering/expr.rs:: lower_expr_to_temp stamps on the produced
Rvalue::BinaryOp / Rvalue::UnaryOp statement via expr.span().
Consumed at the JIT MIR codegen
(crates/shape-jit/src/mir_compiler/rvalues.rs::compile_rvalue’s
Rvalue::BinaryOp / Rvalue::UnaryOp arms) — when the side-table
has an entry for the producing statement’s span, the JIT emits
a method-call equivalent (mirror of the
MirConstant::Method Call-terminator path at
mir_compiler/terminators.rs:315) instead of the native
arithmetic / unary lowering. Result kind flows via the existing
concrete-types conduit (see the trait-method-return chain at
crates/shape-vm/src/compiler/helpers.rs:: infer_top_level_concrete_types_from_mir_with_resolvers).
Why this side-table rather than rewriting MIR at lowering: MIR
lowering has no access to the trait registry / type tracker (it’s
a pure AST→MIR transform; lower_function_detailed takes only
name, params, body, span). The bytecode compiler is the load-
bearing tier that already proves operator-trait dispatch via
type_implements_trait; persisting that decision via this side-
table threads the same proof to the JIT consumer without
duplicating type analysis or routing a trait registry through
MIR lowering (which would be an ADR-level architectural change).
Mirrors the established value_call_return_concrete_types /
monomorphized_method_call_sites side-table pattern.
#[serde(skip, default)] per the same wire-format rationale as
function_return_concrete_types — Span carries source-position
offsets that aren’t a stable wire shape.
Value arg_count is 1 for binary operator dispatch (Add/Sub/
Mul/Div/Mod + Ord-family Greater/Less/GreaterEq/LessEq), 0 for
unary (Neg/Not).
type_schema_registry: TypeSchemaRegistryType schema registry for TypedObject field resolution Used to convert TypedObject back to Object when needed
compiled_annotations: HashMap<String, CompiledAnnotation>Compiled annotation definitions Maps annotation name to its compiled handlers
trait_method_symbols: HashMap<String, String>Trait method dispatch registry: (trait, type, impl selector, method) -> compiled function symbol name.
This is populated by impl-block compilation and used by runtime dispatch (e.g. print() -> Display::display) without relying on symbol naming heuristics.
expanded_function_defs: HashMap<String, FunctionDef>Final function definitions after comptime mutation/specialization.
This is a compile-time inspection artifact for tooling (e.g. shape --expand)
and is not serialized into cached bytecode.
string_index: HashMap<String, u32>Reverse index for O(1) string dedup during compilation.
Maps string content → index in self.strings.
Not serialized — rebuilt lazily on first intern_string call after deserialization.
foreign_functions: Vec<ForeignFunctionEntry>Foreign function metadata table.
Populated by the compiler when fn python ... blocks are compiled.
Linked to language runtimes before execution.
native_struct_layouts: Vec<NativeStructLayoutEntry>Native type C layout metadata table.
top_level_mir: Option<Arc<MirFunctionData>>Cached MIR for the top-level function (JIT v2).
content_addressed: Option<Program>Content-addressed program built alongside the flat bytecode.
When present, this contains per-function FunctionBlobs with content
hashes. It is produced by the compiler as a dual-output alongside the
traditional flat instruction array.
function_blob_hashes: Vec<Option<FunctionHash>>Content hash for each function in functions, indexed by function ID.
This provides stable function identity without relying on function names.
None entries indicate missing content-addressed metadata.
monomorphization_keys: Vec<String>Monomorphization cache keys produced during compilation.
Populated at the end of compile() for diagnostics and integration tests.
Each entry is the mono_key string (e.g. "map::i64_string") for a
generic function that was specialized during this compilation session.
closure_function_layouts: Vec<Option<Arc<ClosureLayout>>>Closure-spec Phase H1: per-function ClosureLayout for every closure
function index. The JIT worker reads this to drive emit_heap_closure
Cranelift codegen for escaping closures (replacing the legacy
jit_make_closure FFI path). None entries indicate the function is
not a closure body, or the layout wasn’t computed. Populated at the
end of compilation from the compiler’s ClosureRegistry. Not
serialized — programs loaded from disk fall back to the FFI path.
trait_vtables: HashMap<String, Arc<VTable>>ADR-006 §2.7.24 Q25.C trait-object vtable registry.
Keyed by "Trait::ConcreteType" (matching the existing
trait_method_symbols key prefix). Built at impl-block
compilation per (impl Trait for Type) pair; consumed at runtime
by op_box_trait_object to allocate Arc<TraitObjectStorage>.
Not serialised because Arc<VTable> is not a stable wire shape;
vtables are rebuilt on cached-program reload from
trait_method_symbols.
has_imported_const_inline: boolR8 W8 Cluster A surface-and-stop flag (2026-05-25).
Set to true by compile_expr_identifier whenever it inlines an
imported pub const initializer expression at a use site. Read by
JITExecutor::execute_with_jit at the JIT compile-step preflight
to refuse JIT compilation of the program — triggering the existing
W12 [jit-fallback] path so the whole program runs under the
bytecode interpreter (which evaluates the inlined PushConst
correctly). VM=JIT convergence preserved.
Background: Cluster A’s compile_expr_identifier intercept emits
the inlined-at-use bytecode (PushConst(<value>)) correctly, but
the JIT’s direct-identifier-eval lowering of that shape fires
jit_print_* FFI with zero-init bits, producing silent-wrong-
output (VM=2, JIT=0 on print(IMPORTED_CONST) bare). Per
supervisor 2026-05-25 path (i) ruling — surface-and-stop is the
binding-compliant fix; root-cause fix in JIT identifier-eval
lowering is v0.4 per docs/v0.3-close-summary.md §5.16
JIT-lowering followup workstream.
NOT serialised because the cached-program reload path recomputes by re-running the inline intercept; nothing here is runtime-mutated, just compile-time state.
has_w17_marshal_residual: boolR8 W9 B1 W17-marshal-return JIT surface-and-stop flag (2026-05-25).
Set to true by compile_expr_function_call whenever it compiles
a direct call whose callee resolves via
resolve_scoped_module_binding_name — i.e. an imported stdlib
function call routed through a Ptr(HeapKind::ModuleFn) callee.
Read by JITExecutor::execute_with_jit at the JIT compile-step
preflight to refuse JIT compilation of the program — triggering
the existing W12 [jit-fallback] path so the whole program runs
under the bytecode interpreter (which dispatches ModuleFn callees
soundly through invoke_module_fn_id_stub + project_typed_return).
VM == JIT convergence preserved.
Background: the JIT-side jit_call_value ModuleFn arm at
ffi/control/mod.rs:704-715 returns TAG_NULL (= the
-1407374883553280 NaN-box null pattern) silently with only a
tracing::debug! line — no error propagation. For module
functions whose VM-side body surfaces clean (e.g. state.serialize
returning the W17-snapshot-resume surface message, or any function
whose TypedReturn arm hits the catch-all in project_typed_return
at crates/shape-vm/src/executor/vm_impl/modules.rs:74), the JIT
path swallows the surface and continues with a null result —
silent-wrong-output VM=ec1 SURFACE / JIT=ec0 garbage on
print(serialize([1.0,2.0,3.0]).len()).
Per supervisor 2026-05-25 path (i) ruling — surface-and-stop is the
binding-compliant fix; root-cause fix in JIT marshal-return-arms
lowering (dispatch_module_fn_call todo!() at
crates/shape-jit/src/ffi/control/mod.rs:252 + the §2.7.10/Q11
kinded handler ABI rebuild) is v0.4 per
docs/v0.3-close-summary.md §5.16 JIT-lowering followup workstream.
Mirrors R8 W7 G.5 V2-verifier preflight + R8 W8 imported-const-inline
surface-and-stop precedents.
NOT serialised because the cached-program reload path recomputes by re-running the call-site intercept; nothing here is runtime-mutated, just compile-time state.
Implementations§
Source§impl BytecodeProgram
impl BytecodeProgram
Sourcepub fn add_constant(&mut self, constant: Constant) -> u16
pub fn add_constant(&mut self, constant: Constant) -> u16
Add a constant to the pool and return its index
Sourcepub fn add_string(&mut self, string: String) -> u16
pub fn add_string(&mut self, string: String) -> u16
Add a string to the pool and return its index. Uses the HashMap index for O(1) dedup.
Sourcepub fn intern_string(&mut self, s: &str) -> StringId
pub fn intern_string(&mut self, s: &str) -> StringId
Intern a string and return a StringId for use in Operand::Name /
Operand::TypedMethodCall. Uses the HashMap index for O(1) dedup.
Sourcepub fn ensure_string_index(&mut self)
pub fn ensure_string_index(&mut self)
Ensure the string_index HashMap is populated. After deserialization, string_index is empty — rebuild it from the strings Vec.
Sourcepub fn resolve_string(&self, id: StringId) -> &str
pub fn resolve_string(&self, id: StringId) -> &str
Resolve a StringId back to a &str.
Panics if the id is out of bounds (indicates a compiler bug).
Sourcepub fn emit(&mut self, instruction: Instruction) -> usize
pub fn emit(&mut self, instruction: Instruction) -> usize
Add an instruction to the program
Sourcepub fn current_offset(&self) -> usize
pub fn current_offset(&self) -> usize
Get the current instruction pointer
Sourcepub fn register_trait_method_symbol(
&mut self,
trait_name: &str,
type_name: &str,
impl_name: Option<&str>,
method_name: &str,
function_name: &str,
)
pub fn register_trait_method_symbol( &mut self, trait_name: &str, type_name: &str, impl_name: Option<&str>, method_name: &str, function_name: &str, )
Register a trait-method dispatch symbol.
Sourcepub fn lookup_trait_method_symbol(
&self,
trait_name: &str,
type_name: &str,
impl_name: Option<&str>,
method_name: &str,
) -> Option<&str>
pub fn lookup_trait_method_symbol( &self, trait_name: &str, type_name: &str, impl_name: Option<&str>, method_name: &str, ) -> Option<&str>
Resolve a trait-method dispatch symbol name.
Sourcepub fn named_trait_impls_for_method(
&self,
trait_name: &str,
type_name: &str,
method_name: &str,
) -> Vec<String>
pub fn named_trait_impls_for_method( &self, trait_name: &str, type_name: &str, method_name: &str, ) -> Vec<String>
List named impl selectors for a trait method on a specific type.
Excludes the default selector (__default__) and returns stable sorted names.
Sourcepub fn find_default_trait_impl_for_type_method(
&self,
type_name: &str,
method_name: &str,
) -> Option<&str>
pub fn find_default_trait_impl_for_type_method( &self, type_name: &str, method_name: &str, ) -> Option<&str>
Find the default trait impl function for a given type and method (any trait).
Searches trait_method_symbols for any entry whose type and method match,
preferring the default selector (__default__). Returns the compiled function
symbol name if found.
This is used by method call dispatch to detect when a trait impl method exists for the receiver type, so that builtin functions with the same name don’t shadow it.
Trait Implementations§
Source§impl Clone for BytecodeProgram
impl Clone for BytecodeProgram
Source§fn clone(&self) -> BytecodeProgram
fn clone(&self) -> BytecodeProgram
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for BytecodeProgram
impl Debug for BytecodeProgram
Source§impl Default for BytecodeProgram
impl Default for BytecodeProgram
Source§fn default() -> BytecodeProgram
fn default() -> BytecodeProgram
Source§impl<'de> Deserialize<'de> for BytecodeProgram
impl<'de> Deserialize<'de> for BytecodeProgram
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Auto Trait Implementations§
impl !Freeze for BytecodeProgram
impl RefUnwindSafe for BytecodeProgram
impl Send for BytecodeProgram
impl Sync for BytecodeProgram
impl Unpin for BytecodeProgram
impl UnsafeUnpin for BytecodeProgram
impl UnwindSafe for BytecodeProgram
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more