Aztec Virtual Machine
But time makes you bolder...
Even children get older... and I'm getting older too.
- Stevie Nicks
Aztec Virtual Machine Operation
Aztec Virtual Machine is responsible for executing Aztec bytecode created by the Build system. The bytecode conforms to the internal specifications of the Aztec VM instruction set and also the definition of the Aztec Class Framework. The Aztec Build system is responsible for handling Aztec source code (by compiling and linking) and Aztec bytecode (by reading, validating and linking). In both cases, the Build system ultimately creates a valid binary executable that is ready for the Virtual Machine to execute.
The Virtual Machine is responsible for managing the set of VM Threads that are created during the course of the Script execution, and it provides the event handling infrastructure for use in the multi-threaded environment. The VM also manages and provides acces to the entire hierarchy of Metadata objects that provide the Script access to the internal makeup of classes, methods and data. This Metadata can be modified dynamically at run-time using dynamic code generation, so the VM is responsible for maintaining proper synchronization to the Metadata hierarchy.
The Aztec Virtual Machine provides a safe, controlled execution environment.
♦ All critical services are monitored and exceptions are fired when necessary.
♦ Math operations (overflow, domain, divide by zero), file I/O, socket I/O, memory, null object references, UI relationships and Dynamic Code errors are all handled automatically.
♦ Object memory cleanup is handled automatically by the Virtual Machine, and the system ensures that object references are valid at all times.
The VM begins execution at the location specified by the Build system, given the rules associated with selecting the Script entry point, and the "-main" command line option. If the entry point is the Run() method of a Thread based class, the VM automatically creates the appropriate thread object and invokes the Run() method accordingly in the context of that thread. If the Script entry point is a global or shared method, the VM internally creates a generic thread object and executes the "Main" method in the context of that thread.
♦ In both cases, the VM attaches the underlying Aztec Thread object to a unique, independent operating system thread.
If the “Main” entry point is a global or shared method, the VM terminates when that instance of the method ends. If “Main” is a class derived from “Thread”, the VM terminates when the Run() method ends.
In addition to the one or more Virtual Machine Thread objects that the Script uses, the system also creates two special VM threads. One is called the Destructor Thread, and it is responsible for executing Aztec object destructors that are marked for execution in the background. It is basically a perpetual server that receives and performs requests for the cleanup of Aztec objects before they are destroyed. It executes the entire set of destructors for each Aztec object, and each object is handled in the order in which it is received. The other special VM thread is called the Ad Hoc Interpret Thread, which is another server that receives requests to execute ad hoc Aztec binary code that was generated by the "Aztec Interpret Utility" tab in the Interpret UI. It executes the code in this special Ad Hoc thread, but it runs in the context of the entire Aztec Script which is already running (if applicable).
Command Line Parameters for Virtual Machine
When an Aztec object goes out of scope, the following rules are used to determine whether it is “cleaned up” in the foreground or the background. An object is cleaned up by invoking the set of destructors for the entire class hierarchy for the object.
♦ If the object was created with the “fore” or “back” keyword in new<>, that setting controls.
♦ Else, if the class is defined with the “fore” or “back” keyword, that setting controls.
♦ Else, if the “-fore” or “-back” Aztec Engine command line option was specified, that setting controls.
♦ Else the Aztec default is used (-back).
Foreground means the VM executes the destructor(s) of an object immediately in-line within the thread when the object is no longer referenced. The destructor is guaranteed to execute before the next VM instruction is executed. This is the basis for deterministic destructors.
Background means the VM executes the destructor(s) of an object by sending it to a separate “Destructor Thread” for execution, as defined above. There is only one Destructor Thread for the entire Script, so each object gets queued up and is executed in the order in which it is received. Due to the timing uncertainty of sending the object request to another thread, and the interaction between multiple VM threads sending destructor requests in parallel, the execution of any given Aztec object's destructor is not deterministic.
The Aztec system default is "-back", and that setting is typically recommended for most situations. In general, it tends to result in a more smoothly running system. However, if the timing of the object cleanup is important to the execution of the Script, then foreground destruction makes sense. As mentioned above, the setting can be applied at the VM level, the class level, and each individual object level, so the Script has a lot of flexibility in how to implement it.
The Virtual Machine packages the "-arg" command line parameters and makes them available to the running Script using the GetArgs(), GetArg() and NumArgs() methods of the Script class.
The Aztec VM is also responsible for honoring the setting of the "-stdio" command line option. By default, the StdIO.Write() and StdIO.Read() methods perform "Aztec Level" standard input and output. The Aztec Engine provides a Console window, available in the Aztec System Menu, and the "Aztec Level" standard I/O is associated with this console window by default. The read operation operates like an old school procedural program, pausing the thread and waiting for keystrokes until the Enter key is pressed.
If the "-stdio" setting used, the VM Console is not used, and instead I/O requests from the Aztec StdIO methods are redirected to the operating system's stdio facility.
If the "-menu" command line option is used, the Aztec Engine displays the Aztec System Menu during the execution of the Script and it remains when the Script terminates. The user can still access the Console and Log dialogs even after the Script is done. If the "-menu" command line option is not used, the Aztec Engine still displays the Aztec System Menu while the Virtual Machine is running. This allows the Console and Logs to be viewed while the Script is running. But once the Script terminates, the system menu goes away and the Aztec Engine application automatically terminates.
Regardless of which "-menu" setting is used, the Aztec Engine provides the ability to turn on and off the ability of the user to cancel the VM while it is running. In the Windows implementation of the Aztec Engine, that means turning on and off the "Cancel Virtual Machine Execution" item in the system menu. The ability for the user to cancel is off by default, so normally the menu item will be disabled while the VM is running. The Script.EnableCancel() method allows the script to grant the user the ability to cancel the VM via the system menu if and when it makes sense.
♦ It is typically a good idea to turn this on during development so a wayward script can easily be cancelled.