Stoffel Virtual Machine Architecture
This page explains the overall architecture of Stoffel’s virtual machine, its core components, and how they work together to execute programs.Rationale
The Stoffel VM uses a register-based architecture designed to efficiently execute programs while maintaining clear execution boundaries. This approach provides a balance between performance and flexibility, enabling the VM to handle both simple scripts and complex applications with multiple function calls, closures, and data structures. The design emphasizes a clean separation between different execution contexts through the activation record system, allowing for intuitive debugging and predictable behavior.Comprehensive Overview
Stoffel is implemented as a register-based virtual machine that executes bytecode instructions. The VM is designed around several key components that work together to provide a complete execution environment:- VMState: The core state of the virtual machine
- VirtualMachine: The primary interface for interacting with the VM
- Activation Records: Function execution contexts
- Value System: The type system for data manipulation
- Instruction Set: The operations that the VM can perform
- Hook System: The instrumentation and debugging framework
VM State
The central component of the VM architecture is theVMState struct, which maintains the current execution state:
functions: A registry of all available functions (both VM and foreign)activation_records: The call stack of active function invocationscurrent_instruction: The currently executing instructionobject_store: Central storage for objects and arraysforeign_objects: Storage for external/native objectshook_manager: System for registering and triggering event hooks
VMState provides methods for executing instructions, managing the activation record stack, and interacting with the hook system. It serves as the core runtime state that the VM manipulates during program execution.
Virtual Machine Interface
TheVirtualMachine struct provides the primary interface for interacting with the VM:
- Manages the VM state using a
Mutexfor thread safety - Offers methods for registering and executing functions
- Provides a standard library of built-in functions
- Exposes the hook system for instrumentation and debugging
Execution Model
Stoffel uses a register-based execution model with the following characteristics:- Program Loading: Functions are registered with the VM, either as VM functions (bytecode) or foreign functions (native code)
- Execution Initialization: An initial activation record is created for the main function
- Instruction Execution: The VM executes instructions sequentially, updating registers and the VM state
- Function Calls: When a function is called, a new activation record is pushed onto the stack
- Function Returns: When a function returns, its activation record is popped from the stack
- Completion: Execution completes when the main function returns or an error occurs
Function Dispatch
The VM supports two types of functions:- VM Functions: Defined as bytecode instructions that the VM executes directly
- Foreign Functions: Implemented in Rust and registered with the VM
-
VM Function Execution:
- Create a new activation record
- Set up function parameters as registers and locals
- Execute instructions until a return occurs
-
Foreign Function Execution:
- Prepare function arguments
- Create a function context with arguments and VM state
- Execute the Rust function
- Process the return value and update register 0
Concurrency and Thread Safety
The VM is designed with thread safety in mind:- The
VMStateis wrapped in aMutexto prevent concurrent access - Foreign objects use
Arc<Mutex<T>>for thread-safe reference counting - Closures use
Arc<Closure>to allow safe sharing
Error Handling
The VM uses a Result-based error handling approach:- Functions return
Result<Value, String>to indicate success or failure - Errors include descriptive messages about the issue encountered
- The VM propagates errors up the call stack to the original caller
- Hook callbacks can also return errors that will abort execution
Instruction Execution Loop
The core of the VM is the instruction execution loop inexecute_until_return():
- Retrieve the current function and instruction pointer
- Load the next instruction
- Trigger the
BeforeInstructionExecutehook - Execute the instruction, updating VM state as needed
- Trigger the
AfterInstructionExecutehook - Continue until a return or error occurs
Memory Management
Stoffel uses Rust’s memory management system for automatic reference counting and garbage collection:- Values are cloned when passed between contexts, avoiding aliasing issues
- Complex values (objects, arrays, closures) use reference counting via
Arc - Foreign objects use
Arc<Mutex<T>>for safe shared access - The VM does not require explicit memory management by users
Component Integration
The VM’s components are tightly integrated to provide a cohesive execution environment:- The instruction set operates on the activation record’s registers and stack
- Functions interact with the object store for object and array operations
- Hooks provide visibility into VM operations across all components
- Foreign functions access the VM state through a controlled context interface
Performance Considerations
The VM design incorporates several performance optimizations:- Register-based operation reduces stack manipulation overhead
- Direct function dispatch avoids interpreter overhead for foreign functions
- Object operations use indexed lookups for efficient access
- Hook system can be selectively enabled or disabled for performance-critical code
- Instruction execution is optimized for common operations