Althread Virtual Machine
Virtual Machine State
The state of the virtual machine is represented by:
- The values of global variables
- The state of communication channels (messages in transit)
- A structure for each process in execution. The state of an executing process includes its execution stack, i.e., the process's local variables, and the value of the instruction pointer, which is the index of the instruction currently being executed.
The execution stack of a process contains no debugging information; it only includes the values of local variables and intermediate expression results in the form of a Literal
array. Expressions using local variables refer to the index of the variable in the process's execution stack. The index of a local variable is determined during compilation, enabling fast access during execution.
To simplify, global variables are stored in a HashMap (dictionary), and their values are directly accessible by name.
Instructions
The virtual machine's instructions are represented by an enum InstructionType
. Each instruction contains fields with the information required for its execution:
Instruction Types
An empty instruction, does nothing.
Evaluates an expression and pushes the result onto the stack. LocalExpressionNode
is the root of a tree representing the expression.
Pushes the given literal onto the stack.
Removes unstack_len
values from the stack.
Replaces the tuple at the top of the stack with its elements. A tuple with 3 elements will be replaced by 3 values on the stack.
Pushes the values of the global variables onto the stack. The only_const
field indicates whether all variables are constants (if so, the instruction can be optimized since it’s not global).
Assigns the value at the top of the stack to the given global variable identifier
and removes unstack_len
values from the stack.
Assigns the value at the top of the stack to the local variable at the given index index
and removes unstack_len
values from the stack.
Declares a variable in the current scope, initialized with the value at the top of the stack, and removes unstack_len
values from the stack.
Starts a new thread executing the program name
with the value at the top of the stack as an argument, then removes unstack_len
values from the stack. Finally, adds the thread's PID to the stack.
Calls the function name
with local arguments at the given indexes, then removes unstack_len
values from the stack. If variable_idx
is provided, the function is a method of the object at the given index. Finally, the function result is added to the stack, if it returns a value.
Jumps to instruction jump_false
if the value at the top of the stack is false, then removes unstack_len
values from the stack. The jump value is relative to the current instruction.
Jumps to instruction jump
. The jump value is relative to the current instruction.
Jumps to instruction jump
while removing unstack_len
values from the stack. If stop_atomic
is true, stops atomic execution.
Checks if a message is available in the channel channel_name
. If so, adds the message and true
to the stack; otherwise, adds false
.
Removes the message from the channel channel_name
(does not add it to the stack).
Starts a wait on a condition using the given dependencies. If start_atomic
is true, begins an atomic section. Dependencies include global variables or channels used in the condition. This instruction does not modify the virtual machine state and merely indicates the start of a waiting zone.
If the top of the stack is false
, jumps to jump
(relative to the next instruction); otherwise, proceeds to the next instruction. In both cases, removes unstack_len
values from the stack.
Sends the value at the top of the stack to the channel channel_name
, then removes unstack_len
values from the stack.
Connects sender_channel
and receiver_channel
between the processes sender_pid
and receiver_pid
. If sender_pid
or receiver_pid
is None
, the current process is used. If a Send
has already occurred, the message is directly transferred.
Begins an atomic section where processes cannot be interrupted, preventing concurrency issues. An atomic section ends with AtomicEnd
and must not contain wait instructions, except at the beginning.
Ends an atomic section.
Terminates the current process.
Terminates all processes.
The InstructionType
enum is defined in the file /vm/src/instruction.rs.