My question is what does the "real" framework do with this when it JITs the code? Surely the same issues apply? We know that ref types can move around memory. How does it handle it?

BTW I now make all functions static, even the instance functions, since I now also pass my own custom "this" pointer and there is no need for the real this pointer.

So, the following C# method...

class Foo
{
    int Multiply(int x, int y)
    {
        return x * y;
    }
}

...now becomes (at tleast the declaration)...

class Foo : public VirtualObject
{
    static int Multiply(VirtualThread* pThread, VirtualObject** pThis, int x, int y);
}

Edit: I can't make virtual functions static. I don't believe this will be a problem since AFAIC the virtual tables themselves are static, so it doesn't matter if the class instance moves around memory.