,Dexter wrote

*snip*

This means that you know where the references to the objects are. If you know this then you can simply update the references when the objects move. An additional level of indirection is not required and it's not efficient anyway.

I think you are right. I was thinking that a currently executing function might have a local reference that could not be updated in such cases but if done correctly then this might not be a problem. So all "local" references to objects should really be references to objects on the "virtual object stack" as either a pointer to the location on the virtual stack, or an index to the virtual stack.

I'll need to give this some more thought but as I said I believe you are correct.

Somewhat related: Since microcontrollers don't support preemptive multithreading (or at least not the ARM microcontroller I'm playing with) I need to emulate that. The way I'm thinking of doing that is something like this:

void SomeClass::SomeFunction(VirtualThread* thread)
{
    // ...code...
    
    if (VirtualMachine.PendingContextSwitch)
        VirtualMachine.SwitchContext(thread);
    
    // ...code...
}

Usually the static VirtualMachine.PendingContextSwitch value would only be checked at the end of a function, or inside a loop (since there is no way to know how long the loop might take to complete). Also if the function is really long then I might add some additional checks.

The VirtualMachine.SwitchContext() call will do a context switch on the CPU. This is obviously very CPU dependent, and on the ARM processor you call the SWI instruction. Not sure how to do it on an x86 processor but it would not be too difficult to figure out (I'll stay away from x64 for now).

The VirtualMachine.PendingContextSwitch value itself would be set to true either periodically by a timer in VirtualMachine on x86, or by a hardware timer interrupt on the ARM processor.

The above mechanism has the advantage that I can control exactly where the code can be preempted, and maybe update all local references (if it is even needed) if VirtualMachine.SwitchContext returns true. Something like:

void SomeClass::SomeFunction(VirtualThread* thread)
{
    // ...code...

    if (VirtualMachine.PendingContextSwitch) && VirtualMachine.SwitchContext(thread)
    {
        // update all local references
    }

    // ...code...
}

Since most of the time PendingContextSwitch will be false, the check should not add much overhead, even inside tight loops. Once again, would this be the way the smart guys do it, or am I completely missing something here?

EDIT: Does anyone know what is up with the code formatting? Sometimes it insists putting everything on the same line, no matter whether you put newlines or Shift+newlines. I removed the code from the code blocks to make them readable.