Autolang Runtime & VM
Autolang runs on a lightweight, deterministic C++ Virtual Machine designed to execute compiled bytecode safely and with minimal memory footprint.
Core Design Principles
Unlike heavy VMs (like JVM or .NET) that require JIT warming and large memory arenas, the Autolang VM is built for zero-overhead embedding.
Deterministic Latency
No JIT compiler compilation spikes and no stop-the-world garbage collection pauses. Execution flows on a single thread with absolute clock predictability.
Embedded Native Client
Implemented entirely in modern C++ with zero external runtime dependencies. Packaged as a clean static/dynamic library or WebAssembly binary.
Zero-Trust Sandboxing
Built-in hardware/OS abstraction layers. Memory operations, filesystem limits, and HTTP endpoints are strictly controlled and verified by the host shell.
Execution Model: Stack-Based Bytecode Interpreter
The VM uses a Stack-Based Bytecode Interpreter model. It evaluates instructions sequentially by pushing and popping operands from a lightweight stack.
Bytecode Decoding
Bytecode execution is wrapped in a highly optimized dispatch loop. Instructions decode into opcodes mapped to low-level VM routines in C++ with minimal branching.
Continuous Memory
Variables, stack records, and bytecode lists are arranged sequentially in memory. This reduces L1/L2 cache misses compared to dynamic heap-heavy languages.
Stack & Frame Allocation
When functions are invoked, the VM manages execution scopes via memory frames. The compiler pre-calculates the local variables capacity, enabling the VM to allocate stacks in O(1) space.
- ⚡
Lock-Free Frames
Functions claim offset segments on a sequential block buffer. Space allocations require zero synchronization locks.
- ♻️
Instant Scope Reclaims
When functions return, the top frame pointer drops back instantly, releasing local slot handles without search sweeps.
- ↕️
Dynamic Scaling Stack
The execution stack expands on deep recursions and dynamically shrinks back when stack depth returns to normal.
Memory Architecture & Lifecycle
Autolang bypasses system allocators using a structured arena layout for high-throughput, deterministic reference counts.
AreaAllocator & ObjectManager
The VM allocates large contiguous memory pools up front. The ObjectManager uses these arenas to distribute sequential storage blocks. Reclaiming the whole arena at compile-end guarantees zero dynamic leaks.
Cached Primitive Instances
Small immutable values (e.g. static integers or booleans) are cached internally. The VM points reference requests directly to these pre-allocated nodes instead of making new allocations.
Immediate Reference Counting
Objects track reference owners. When the ref count hits zero, resources are freed instantly inside free(), bypassing background collector overhead.
Runtime Type Representation: AObject
At the binary level, all Autolang references are managed using the unified C++ struct AObject. It contains metadata and an 8-byte union payload pointing to raw primitives or specialized structures.
struct AObject {
enum Flags : uint32_t {
OBJ_IS_FREE = 1u << 0,
OBJ_IS_CONST = 1u << 1, // Bypasses reference counting
OBJ_IS_NATIVE_DATA = 1u << 2, // Wraps host-managed native data
OBJ_IS_NO_DATA = 1u << 3,
OBJ_IS_ARRAY = 1u << 4,
OBJ_IS_SET = 1u << 5,
OBJ_IS_MAP = 1u << 6,
OBJ_HAS_MEMBER_DATA = 1u << 7,
OBJ_IS_JS_OBJECT = 1u << 8 // JSObject binding (Emscripten WebAssembly)
};
ClassId type;
uint32_t refCount;
uint32_t flags = 0;
union {
int64_t i; // Int representation
double f; // Float representation
uint8_t b; // Bool representation
FunctionObject *function; // Closures and Function pointer
NormalArray<AObject *> *member; // Class instance members / Array elements
AString *str; // Autolang String representation
ANativeData *data; // Native data pointer bound to host
ABytes *bytes; // Binary buffer (std/bytes)
#ifndef NO_INCLUDE_LIBS_JSON
nlohmann::json *json; // Native JSON node (std/json)
#endif
#ifdef __EMSCRIPTEN__
emscripten::val *jsObject; // JS reference in WASM environment
#endif
};
inline void retain() {
if (flags & Flags::OBJ_IS_CONST) return;
++refCount;
}
};Memory Reclamation (`free`)
When free() is invoked: primitive values (ints, floats) are simply marked with OBJ_IS_FREE for pool reuse. Custom objects containing member variables loop through the memberarray and decrement the child objects' reference counts.
Host-Bound Native Data
If the OBJ_IS_NATIVE_DATA flag is active, the garbage collector invokes the host-supplied C++ destructor function, allowing custom native objects to clean up their external dependencies safely.
Hashing & Equality Operators
The VM uses custom hash maps and sets. Standard comparators and hash generators are defined natively to support dynamic collections (Map and Set).
// Custom hash implementation for map/set structures
struct AObjectHashable {
inline size_t operator()(const AObject *obj) const {
switch (obj->type) {
case DefaultClass::intClassId: return obj->i;
case DefaultClass::floatClassId: return hashFloat(obj->f);
case DefaultClass::stringClassId: return fnv1aHash(obj->str);
default: return reinterpret_cast<size_t>(obj);
}
}
};
struct AObjectEqualable {
inline bool operator()(const AObject *a, const AObject *b) const {
if (a->type != b->type) return false;
switch (a->type) {
case DefaultClass::intClassId: return a->i == b->i;
case DefaultClass::floatClassId: return a->f == b->f;
case DefaultClass::stringClassId: return a->str == b->str;
default: return a == b; // Pointer identity comparison
}
}
};FNV-1a String Hashing
Strings are hashed on their character array contents using the Fowler–Noll–Vo FNV-1a non-cryptographic hash algorithm, guaranteeing rapid table distributions.
Pointer Identity Fallback
For standard user-declared classes and arrays, equality defaults to comparing their physical memory pointer addresses (strict identity equality).
