Documentation
XCX Runtime Core and FFI Subsystem
The XCX runtime acts as an intermediary layer between the Virtual Machine interpreter, JIT execution blocks, and the underlying platform operating system.
Service Registry (src/runtime/builtin/registry.rs)
The Virtual Machine and JIT compiler access native services through a centralized registry. The built-in services registry maps and re-exports modules from the builtin directory, dividing capabilities into clear namespaces:
json: Core JSON manipulation and query injections.math: Randomization algorithms, pseudo-random tables, and exponent powers.string: Case converters, trimmers, string slicers, and parsers.io: Text output (print buffers), input scanners, and ANSI terminal controls.net: HTTP request drivers, socket listeners, and response writers.crypto: Password generators, hash mechanisms (bcrypt/sha256/tokens).store: Disk caching, file operations, key-value data structures.
These namespaces compile cleanly into static symbols that are shared across both the interpreter runtime loops and compiled JIT functions.
FFI Linking and Conventions (src/runtime/ffi_helpers/)
To invoke Rust-implemented built-ins from machine code, JIT-compiled functions must use a standardized calling convention. The files under ffi_helpers/ implement cross-linkage interfaces prefixed with xcx_jit_* using standard C ABI bindings.
ABI Signature Pattern
FFI functions conform to raw call configurations:
1. Name Mangling Elision: Extracted with #[unsafe(no_mangle)] and pub unsafe extern "C".
2. Output Handling: Functions returning a heap-allocated structures or dynamic type write their returned values to an output pointer reference (out: *mut Value).
3. Primitive Returns: Methods returning pure numbers or flags return standard primitives (i64, f64, or u8/bool) directly in registers:
NaN-Boxed Parameter Conversion
Because the VM stores parameters inside quiet-NaN boxing slots, FFI functions must unpack arguments before processing and repack them before returning:
1. Reconstruction: Helper accepts raw components (bits: u64, tag: u64) and aggregates them into a Value struct instance.
2. Tag Extraction: Queries the tag against heap boundaries or maps it directly to heap-allocated object wrappers:
3. Rust Operations: Unwraps data payload into safe Rust types (e.g. converting utf8 byte vectors into a String), executes the standard operation.
4. Repacking: Allocates output objects on the allocator heap, packs them under appropriate type tags (TAG_STRING, TAG_ARRAY, etc.), and updates the target *out pointer.
Panic and Exit Propagation
If FFI functions run into unrecoverable invalid states (e.g. division by zero, type tag mismatch, or database connection loss):
- They report errors back by returning non-zero error flags (or sentinel error values) and updating diagnostic state fields within the current thread's executor context.
- The JIT code checks these return flags after calling FFI functions and branches to deoptimization/exception-handling blocks if an error is flagged, preventing unsafe unwinding over the FFI boundary. Rust panics are NEVER propagated over the C ABI boundary.