Quote
rdon...@southeast.net (R.E.Donais) wrote:
[snip discussion on creating a tail recursive method ...]
My previous asm/inline solution assumes a static method. If "run" is a virtual
method, you could not iterate through the list, but would have to invoke the
proper virtual method for each object.
In order to reference a virtual method you have to know its offset within the
object's virtual method table (VMT). It's a shame that the compiler doesn't
contain a feature to return this information. In order to determine the
offset, you have to count all virtual methods, in the order that they were
initially declared. The position has nothing to do where a virtual method may be
declared in a descendant object, just its position when the method was declared
for the first time.
For example, if your object was a descendent of tObject, then tObject.Done would
be the first virtual method. If you then declared run and over-ride done, done
would still be first regardless if it appeared before or after "run" in the
descendant object.
As you count virtual methods, number the first method 0, the second 1, third, 2,
etc. Then define the method's offset as:
CONST MyObject_RUN = 0 * Sizeof(Pointer) + VMTheaderSize;
or if a direct descendant of tObject, maybe:
CONST Done_Method = 0 * Sizeof(Pointer) + VMTheaderSize;
Run_Method = 1 * Sizeof(Pointer) + VMTheaderSize;
PROCEDURE MyObject.Run;
BEGIN
{ Do some stuff }
{ ... }
ASM
les DI,[Self]
les DI,[ES:DI.pNextObj] { get next object }
mov AX,ES
or AX,DI
jz @Exit
mov [Self.Word.0],DI { update Self to point }
mov [Self.Word.2].ES { to the next object & }
mov BX,[ES:DI] { get offset to the VMT }
mov SP,BP { discard local variables. if any }
pop BP { restore caller's stack frame }
{ At this point, the stack has been restored to }
{ the state it was in just after the original }
{ call. Since that return address is currently }
{ at the top of the stack, we can jump through }
{ the appropriate VMT entry to the new address }
{ to simulate a call to the new run method. }
JMP DWORD PTR [DS:BX.MyObject_RUN_Method]
@Exit:
end;
...red
cc Mark Rogers <m...@holly.demon.co.uk>