[Mono-devel-list] VTable & Interfaces
Willibald Krenn
Willibald.Krenn at gmx.at
Tue Mar 1 10:50:59 EST 2005
Ben Maurer schrieb:
> The answer is `yes, you have to, but it doesn't cost nearly as much as
> you think it does'
> It wouldn't be too hard to set a little hack where each class has two
> extra fields:
>
> MonoClass* first_child
> MonoClass* next_sibling
>
> This would allow us to easily just look at the people who derived.
Yes, that would be possible. Additionally some way of narrowing down the
search in the interface part of the VMTs would be nice. I have to think
about this.
> Also, why do you need to patch the actual vtable? Isn't the address to
> the method going to be embeded in quite a few places anyways?
Well, this won't work with recompilable methods anymore: It's
potentially unsafe to overwrite the first XX bytes of an active method,
because there could be code like
0:push bp
:..
l1:..
:call <another method>
:..
XX:..
:call <another method>
:jnz <l1>
So before a method can be patched with a stub that calls a service
routine that patches the caller code, we have to do a stack walk of each
running thread and if the to-be-replaced method is found in the walk, we
have to cancel the replacement and try again at a later time.
(Potentially never being able to replace the method because of loops or
high call frequency ..)
The cleaner solution is to always do indirect calls and simply exchange
the pointer in the table upon method replacement: No code patching
necessary and the stack walks are only necessary if we want to free the
old method.. (But not in case we want to patch the code.)
Due to branch prediction I don't think the penalty for doing indirect
calls is too high. (Especially as the pointer table page will 99% be in
cache..)
Additionally the magic tramp call (and thus the lmf/regsave code) is
only executed once for a new method - all other calls go directly to the
newly compiled method and not over the magic tramp as now.
BTW: With this model it's still possible to embed the address in the
caller if we find recompilation is not worth the effort. (This is
because the indirect call is about 8 bytes (AMD64) and the direct one is
5 bytes..)
This still leaves virtual methods out of the equation: Basically each
virtual method has an entry in the VMTs of different classes. As we
won't install patch code, we have to replace all these pointer
occurrencies if we want to replace a virtual method.
(Alternatively we could introduce another indirection in the sense that
the VMT entries are pointers to locations where the real address of the
method is saved. However, this would mean an additional mov (with memory
access) in case of a virtual method call and therefore I think this is a
bad idea. To preserve runtime performance it's better to look up all VMTs..)
So I'll do the indirect calls this week - I then hope that the framework
is ready after this work is done!
Willi
More information about the Mono-devel-list
mailing list