Computed gotos on Reddit

Dmitry Olshansky dmitry.olsh at gmail.com
Tue Jul 24 12:50:09 PDT 2012


On 24-Jul-12 21:03, Walter Bright wrote:
> On 7/24/2012 6:58 AM, Dmitry Olshansky wrote:
>>>> void op_1()
>>>> {
>>>>      ...//some code for instruction 1
>>>>      opcode = cast(function void ())code[pc++];
>>>>      goto opcode(); //opcode is pointer to function op_xx
>>>> }
>>>> //can do without goto fn() iff tail call is GUARANTEED
>>>
>>> I believe you can do this with:
>>>
>>>      switch (pc++)
>>>
>>> and there are the same number of indirections.
>>
>> And how is pc is supposed to be an opcode? It's a counter after all...
>
>      switch (pc++)
>
> and
>      goto code[pc++]
>
> are the same (same as in same number of indirections).
>
>      switch (code[pc++])
>
> and
>
>      goto code[pc++]()
>
> are the same, too.

It's not. Let's get to assembly then. It's an illustration as I'm no 
expert and may have made some illegal shortcuts in this listing.

goto code[pc++]() is roughly:

mov ecx, [ebx]
inc ebx
jmp [ecx]

switch(code[pc++]) is:

mov ecx, [ebx]
inc ebx
mov ecx, [edx+ecx] // assuming jump table is at edx
jump [ecx]

If you count only jumps, then yes, the same number of indirect jumps. 
BUT note the use of extra register to point to the table & extra read of 
jump table contents. (BTW I assumed jump table address is loaded in 
register, a luxurious assumption esp. on 32bit).

Again, the biggest practical limitation of switches (loosing some 
performance hurts but not show stopper) is that last time I checked dmd 
doesn't try to merge equivalent jump tables.

Thus I can't put VM dispatch switch at the of each branch of main opcode 
switch (see my earlier posts) to help branch predictor. It just spawns 
ton of new tables, of course it has lower performance and wastes data cache.

-- 
Dmitry Olshansky


More information about the Digitalmars-d mailing list