Summary

Topics: Deferred calls and Multiple stacks

Not much happened in the last week. Some work was done on deferred calls and multiple stacks.


Deferred calls

Deferred calls are somewhat similar to those of Go. Viua now provides a defer instruction that registers a call to be performed when current stack frame is being logically discarded.

Deferred calls are now correctly invoked during the "good" path: on returns and on tailcalls. Invocations during stack unwinding in case of exception are not there, yet, as this has proven to be more tricky to implement.

What makes deferred calls in Viua less powerful than in Go is the fact that Viua deferred calls are currently run after the frame that registered them is discarded, what means that all pointers to values in that frame are invalidated by the time the deferred call is invoked. This also means that it is (currently) impossible to move or copy values from frame into a deferred call just before the frame is discarded, and to use them in the deferred call's frame. This behaviour is clearly unwanted, and will be fixed in future versions.

An important note is that deferred calls are made possible because Viua is now able to maintain several different stacks inside a single process.


Multiple stacks

Viua is now able to maintain several different stacks inside a single process. Stacks share global and static register sets. Only one stack is ever active so this sharing is safe.

Why multiple stacks?

While a process encapsulates an execution actor, a single stack encapsulates a call history. And sometimes (maybe even more frequently than one could expect) histories of calls inside process should remain separate. To give a few examples:

  • an interrupt arrives and should be handled
  • the VM must invoke some code in the context of a user process
  • a pattern matching call must be performed
  • a message-filtering call is requested

Interrupts

An interrupt arrives and should be handled but the call did not originate from inside the process that handles the interrupt, and bears no relation to what is currently on the active stack.

This is a perfect opportunity to use multiple stacks. The interrupt-handling function will be called on a separate stack instead of being appended ad-hoc to whatever the process is doing. Call histories remain separate, the interrupt is handled, and the process continues its work.

Small disclaimer: interrupts are not implemented in Viua VM yet, but are discussed here as their implementation is made possible by the introduction of multiple stacks.

VM-invoked code

VM may inject code to be executed in context of user processes; e.g. destructors, or deferred calls. Such calls might be appended to the current stack of a process, but that would require hackish code and tricks. A much cleaner and elegant solution is to run VM-invoked calls on separate stacks.

Exception continuity (i.e. exceptions travelling between calls up the stack in a logical manner) is maintained as the stacks are themselves stacked. If an exception is thrown in a VM-invoked deferred call the exception will be correctly propagated to "parent" stack.

Pattern matching and message filtering

Both features are just plans, so take this with a pinch of salt.

Pattern matching and message filtering may be abstracted as function calls. User (or the VM) supplies a function to be used, the VM invokes it on a separate stack, and the result is moved back to the parent stack.

This model will provide an elegant solution to message filtering. Currently programs running on Viua VM have no means of filtering incoming message except maintaining their own buffer in a global vector and running filters on that. Current solution is usable, but worse than bad, and message filtering (enabled by multiple stacks) will be the solution.